数据清洗之数据统计--分组 聚合 分组对象与apply函数 透视图与交叉表
数据清洗之数据统计
In [ ]:
import pandas as pd
import numpy as np
import os
os.chdir(r'F:\CSDN\课程内容\代码和数据')
在线杂货店订单数据
- customer :消费者ID,一个消费者可能有多个订单
- order :订单ID,订单的唯一标识,不重复
- total_items :订单中购买的商品数量
- discount% :收到的总折扣百分比
- weekday :下单时间:星期几下单,1-7 为 周一至周日
- hour :下单时间:几点下单,0-23 为二十四小时制
- Food% :食物在订单总价中占比,食物为非生鲜类食物
- Fresh% :生鲜类食物在订单总中占比
- Drinks% :饮品在订单总价占比,由于高糖税可能导致总折扣为负
- Home% :家居用品在订单总价中占比
- Beauty% : 美妆类产品在订单总价中占比
- Health% :保健类产品在订单总价中占比
- Baby% :母婴类产品在订单总价占比
- Pets% :宠物用品在订单总价占比
In [ ]:
df = pd.read_csv('online_order.csv',encoding = 'gbk',dtype={'customer':str,'order':str})
In [ ]:
df.dtypes
1. 数据分组运算
- df.groupby('a')
- df.groupby(by = ['a','b'])
- df[['a','b','c']].groupby('a')
- df[['a','b','c']].groupby(by = ['a','b'])
- 使用单个分组变量
- 使用groupby方法(count median max min sum mean……(◐‿◑))
In [ ]:
df.head(4)#查看数据
In [ ]:
grouped = df.groupby('weekday') #创建分组对象,按照星期进行分组
In [ ]:
grouped.mean() #调用方法取均值
In [ ]:
grouped.sum()['total_items']# 计算不同的星期,商品数量的总和
In [ ]:
grouped = df.groupby(by =['customer','weekday'])#创建分组对象(以列表形式传入),按照用户和星期
grouped.sum()['total_items']#查看这一个分组下这个用户在某一天的订单综合
In [ ]:
grouped.sum()['total_items'].head(50) #调用方法,计算不同的用户周一到周天的订购商品数量的总和
2. 聚合函数使用
- 使用聚合函数agg
- agg是一个作用于series或者DataFrame的函数,主要目的是针对分组后的对象,使用相关函数进行计算
In [ ]:
grouped = df.groupby('weekday')#创建分组对象,按照周一到周天进行分组
In [ ]:
grouped.agg([np.mean,np.max]).head(20) #对分组后对象,计算每一个weekday分组的元素的 均值和总和
In [ ]:
grouped.agg({'total_items':np.sum,'Food%': [np.mean,np.median]}) #对2个变量分别计算不同的统计量
这里对总订单求和,对食物比例求取均值和中间值
In [ ]:
df[['total_items','Food%','Drinks%']].agg([np.sum,np.mean]) #也可以直接对数据进行汇总
这里先选取对象,再计算其中的计算方式
3.分组对象与apply函数
- 使用apply函数
- 0代表沿着行的方向作用,1代表沿着列的方向作用
In [ ]:
grouped = df.groupby('weekday')
In [ ]:
grouped.apply(np.mean)[['total_items','Food%']] #可以做聚合
- 体验一下apply 中,axis=0 或者 axis=1的区别
In [ ]:
df.columns
In [ ]:
var_name = ['Food%', 'Fresh%', 'Drinks%', 'Home%', 'Beauty%', 'Health%', 'Baby%',
'Pets%'] # 不同类型的商品占比
In [ ]:
df[var_name].apply(np.sum,axis = 0) #相当于视图中计算每列的总和
df[var_name].apply(np.sum,axis = 1) #相当于视图中计算每行的总和
从矩阵上理解的话,这个是一个总的list里面套了好多个并行的小list,
而axis=0则相当于每一个小list中取相同次序的某一个
axis=1则相当于每次对其中一个list的内容作处理
In [ ]:
df['sum'] = df[var_name].apply(np.sum,axis=1) # 相当于计算每行的总和
In [ ]:
var_name.append('sum')
In [ ]:
df[var_name] #查看数据,会发现总和为1
In [ ]:
df[var_name].apply(lambda x: x[0] - x[1],axis = 1) #计算食物在订单总价中占比 - 生鲜类食物在订单总中占比
#对与每一个小的list(这里相当于x),将它的第一列减去第二列
4. 透视图与交叉表
In [ ]:
#读取数据
df = pd.read_csv('online_order.csv',encoding = 'gbk',dtype={'customer':int,'order':str})
In [ ]:
df.columns
In [ ]:
fill_value是填充值
# 单个变量
#margin =True 表示是否需要总计
pd.pivot_table(data= df,index='weekday',values='total_items',aggfunc=[np.sum,np.size],margins=True,margins_name='总计')#按照周一到周天计算购买的商品数量总数和次数
margins=True是在计算完每一行数据以后总的那一列的 再进行一次统计
pd.pivot_table? 如果你全都忘记了,记得输入一个‘?’来查看需要赋值的参数
- 交叉表
- 交叉表更多用于计算分组频率
In [ ]:
# 使用交叉表
#是一种计算分组频数的特殊透视表
# 不同的星期,不同的折扣交叉表
pd.crosstab(index =df['weekday'], columns=df['discount%'],margins=True)
In [ ]:
#按照行进行汇总,计算频数占比
pd.crosstab(index =df['weekday'], columns=df['discount%'],margins=True(是否需要统计), normalize='all'(对数据进行标准化))
In [ ]:
#按照行进行汇总,计算频数占比
pd.crosstab(index =df['weekday'], columns=df['discount%'],margins=True, normalize='all') #index表示计算行百分比,columns表示计算列百分比
In [ ]:
pd.crosstab(index =df['weekday'], columns=df['discount%'],margins=True, normalize='columns') #index表示计算行百分比,columns表示计算列百分比
风雨兼程,前程可待!