数据分析(五)--pandas(文件读写,合成表,增删改查,数据清洗,时间数据处理,统计函数)

一、文件的读写

xlsx–工作簿–文件夹

sheet–表

import pandas as pd

detail = pd.read_excel('data/meal_order_detail.xlsx')
print(detail.shape)    # 默认读取的是sheet1

如果想读别的sheet表,使用sheetname参数,指定想要读取的表的索引位置。

detail_sheet2 = pd.read_excel('data/meal_order_detail.xlsx',sheetname=1)
print(detail_sheet2.shape)
print(detail_sheet2.describe())

二、将多个表合成为一个表

对于excel表格,可以利用专门的xlrd库来进行操作。

import pandas as pd
import xlrd

file_path = 'data/meal_order_detail.xlsx'
# 1.拿到工作簿
wb = xlrd.open_workbook(file_path)
# print(wb)    # <xlrd.book.Book object at 0x0000000006188C50>
# 2.拿到sheet列表
sheets = wb.sheet_names()
# print(sheets)    # ['meal_order_detail1', 'meal_order_detail2', 'meal_order_detail3']
# 3.合成为一张表
total = pd.DataFrame()
for i in range(len(sheets)):
    sheet = pd.read_excel(file_path,sheetname=i,skiprows=0,encoding='utf-8')
    # print(type(sheet))
    print(sheet.shape)
    total = total.append(sheet)
print(total.shape)
# 4.保存
wb = pd.ExcelWriter('detail.xlsx')
total.to_excel(wb,'Sheet1')
wb.save()

三、使用pandas对数据进行增删改查

(一)查找

1.loc[行索引名称或条件,列索引名称]

值域:为闭区间

索引名称可以是当前不存在的(增加)

# 使用条件获取表格数据# 读取order_id=458的,dishes_name和order_id两列
result = detail.loc[detail['order_id']==458,['dishes_name','order_id']]
print(result)print(result.describe())

2.iloc[行索引位置,列索引位置]

值域:前闭后开

索引位置必须要是当前存在的

(1)想要的行是连续的–切片

# 读取order_id=417的,dishes_name和order_id两列
result2 = detail.iloc[0:5,[1,5]]
print(result2)
print(result2.describe())

(2)想要的行是不连续的

方法1:行索引

result2 = detail.iloc[[0,2,3,4],[1,5]]
print(result2)
print(result2.describe())

方法2:使用条件

类似于遮罩

print((detail['order_id'] == 417).values)
result2 = detail.iloc[(detail['order_id'] == 417).values,[1,5]]
print(result2)
print(result2.describe())

(二)修改

loc/iloc–查找

修改:就是在查找的基础上赋值

1.针对某一个单元格

查找

cell_00 = order.iloc[0,0]
print(cell_00)

查找name为苗宇怡那个单元格,将苗宇怡改为老苗

cell_0_21 = order.iloc[0,20]
print(cell_0_21)
order.iloc[0,20] = '老苗'
print(order.iloc[0,20])

2.批量修改

将emp_id值为982的修改为98200

order.loc[order['emp_id']==982,'emp_id'] = 98200
print(order.loc[order['emp_id']==98200,'emp_id'])

(三)删除

格式:表对象.函数

1.drop()

(1)删除行

def drop(self, labels, axis=0, level=None, inplace=False, errors=‘raise’):

axis=0–删除行,axis=1–删除列

inplace–是否影响原数据(order),默认False,不影响

# 直接指定索引
print(order.shape)
order.drop(labels=[0,1,2],axis=0,inplace=True)
print(order.shape)
# 还可以使用<class 'pandas.core.indexes.numeric.Int64Index'>对象作为labels
# 具体用法见后面的数据清洗

(2)删除列

# (1)删除一列
print(order.shape)
print(order.columns)
order.drop(labels='mode',axis=1,inplace=True)
print(order.shape)
print(order.columns)

# (2)删除多列
print(order.shape)
order.drop(labels=['mode','check_closed'],axis=1,inplace=True)
print(order.shape)

2.dropna()

def dropna(self, axis=0, how=‘any’, thresh=None, subset=None,inplace=False):

axis=0–按行删除,axis=1–按列删除

how=any–行或列中只要有一个值为空,就删除

how=all–行或列中所有的元素都是空,才删除

print(order.shape)
order.dropna(axis=1,how='all',inplace=True)
print(order.shape)

3.drop_duplicates()–去重(针对行)

def drop_duplicates(self, subset=None, keep=‘first’, inplace=False):

print(order.shape)
order.drop_duplicates(inplace=True)
print(order.shape)

(四)增加

在原有基础上,要么增加一行,要么增加一列。

1.增加一列

将时间差作为一列,插入表中

order['lock_time'] = pd.to_datetime(order['lock_time'])
order['use_start_time'] = pd.to_datetime(order['use_start_time'])
delda_time = order['lock_time']-order['use_start_time']
order['delta_time'] = delda_time
print(order)

列中元素皆相同,可以直接赋值一个数。

order['test'] = 1
print(order['test'])

2.增加一行

print(order.shape[0])
li = []
for i in range(21):
    li.append(i)
order.loc[order.shape[0],:] = li
print(order.shape[0])

四、时间数据的处理

import pandas as pd

order = pd.read_table('data/meal_order_info.csv',sep=',',encoding='gbk')    # DataFrame

1.类型转换

start_time = order['use_start_time']    # Series
# print(start_time[0],type(start_time[0]))    # 2016/8/1 11:05 <class 'str'>
# 为了方便对日期时间进行操作,需要将字符串类型的日期时间数据转换成日期时间类型
result = pd.to_datetime(start_time)    # Series
# print(result[0],type(result[0]))    # 2016-08-01 11:05:00 <class 'pandas._libs.tslib.Timestamp'>

# 此时order的use_start_time数据依然是str类型
# print(type(order['use_start_time'][0]))    # <class 'str'>
# 需要给order的use_start_time数据赋值为转换类型之后的数据
order['use_start_time'] = result
# print(type(order['use_start_time'][0]))    # <class 'pandas._libs.tslib.Timestamp'>

# 同理,处理lock_time列
lock_time = order['lock_time']
order['lock_time'] = pd.to_datetime(lock_time)

2.计算

(1)常用属性和方法

  • year
  • month
  • day
  • week
  • weekday()
  • weekday_name
# 年份
# for i in order['lock_time']:
#     print(i.year)
years = [i.year for i in order['lock_time']]
print(years)

# week--当前年份的第几周
# weeks = [i.week for i in order['lock_time']]
print(weeks)

# weekday()--星期几
# 星期一--0,星期二--1,...
weekdays = [i.weekday() for i in order['lock_time']]
print(weekdays)

# weekday_name--星期几
# Monday,Tuesday,...
weekday_names = [i.weekday_name for i in order['lock_time']]
print(weekday_names)

(2)聚合函数

# min()/max()
print(order['lock_time'].min())
print(order['lock_time'].max())
# 时间差
delta = order['lock_time'].max()-order['lock_time'].min()
print(delta)

练习

统计每个订单的点单所用时间

delta_time = order['lock_time']-order['use_start_time']
# print(deta_time)
print('最小:',delta_time.min())    # 最小: -1 days +00:05:00
print('最大:',delta_time.max())    # 最大: 16 days 00:08:00

显然,数据存在不合规的情况。

这就涉及到了数据预处理,即数据清洗。

五、数据清洗

数据清洗

  1. 清洗掉不合规的数据
  2. 清洗掉空值数据
  3. 清洗掉重复数据
# 分析待处理数据,lock_time早于use_start_time明显是不合规的
print(type(delta_time[0]))    # <class 'pandas._libs.tslib.Timedelta'>
# index[]--返回符合条件的索引
result1 = delta_time.index[(delta_time<pd.to_timedelta(0))]
print(result1)

# lock_time与use_start_time的跨度如果超过一天,也是不合规的
print(delta_time.dt.days)
result2 = delta_time.index[(delta_time.dt.days>0)]
print(result2)

1.分别删除

print(order.shape)
order.drop(labels=result1,axis=0,inplace=True)
print(order.shape)
order.drop(labels=result2,axis=0,inplace=True)
print(order.shape)

那要是条件多了,这种方法就low了。

2.统一删除

result = delta_time.index[(delta_time<pd.to_timedelta(0))|(delta_time.dt.days>0)]
print(order.shape)
order.drop(labels=result,axis=0,inplace=True)
print(order.shape)

结果

这回得到的数据就比较合规了。

print('~~~~~~~~~~~~~~~~~~~~~~~~~~清洗后~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
delta_time = order['lock_time'] - order['use_start_time']
print('最小:',delta_time.min())    # 最小: 0 days 00:00:00
print('最大:',delta_time.max())    # 最大: 0 days 00:55:00

# 平均点餐时间
print('平均:',delta_time.mean())    # 平均: 0 days 00:11:20.639470
# 作用:餐饮--翻桌率

六、统计函数

同numpy

import numpy as np
import pandas as pd

arr = np.array([1,2,3])
np.sum(arr)
arr.sum()

order = pd.read_table('data/meal_order_info.csv',sep=',',encoding='gbk')
# print('营业额:',order['accounts_payable'].sum())
print('营业额:',np.sum(order['accounts_payable']))

练习

多条件查询:| &

生成表格时不要原索引:index=Flase

import pandas as pd

# 有users.xlsx文件,完成如下操作:
# 1.打开该文件,统计该表格有行数和列数
file_path = 'users.xlsx'
users = pd.read_excel(file_path)
print(users.shape)

# 2.将表中所有"NAME"="admin"的数据修改为:“Administrator”
users.loc[users['NAME']=='admin','NAME'] = 'Administrator'
print(users.loc[users['NAME']=='Administrator',:])

# 3.表中有“LAST_VISITS”和“FIRST_VISIT”两个字段,分别表示最后登录时间和第一次登录时间,请计算这两个时间的时间间隔。
delta_time = users['LAST_VISITS'] - users['FIRST_VISIT']
print(delta_time)

# 4.将年龄小于30岁且性别为男性的数据单独保存成一个文件,文件名为:“nan_31.xlsx”
# users_age = users.loc[users['age']<30,:]
# new_users = users_age.loc[users_age['sex']=='男',:]

new_users = users.loc[(users['sex']=='男')&(users['age']<30),:]
print(new_users.shape)
wb = pd.ExcelWriter('nan_31.xlsx')
new_users.to_excel(wb,'Sheet1',index=False)
wb.save()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章