目录:
- 学习目标
- 分组对象DataFrameGroupBy
- 数据准备
- df.groupby分组函数返回分组对象
- 分组对象其他API
- 取出每组第一条或最后一条数据
- 获取分组后每组的名称
- gs.get_group()按分组依据获取其中一组
- 分组聚合
- 分组后直接聚合
- 分组后指定单列或多列聚合
- 分组后使用多个聚合函数
- 分组后对多列分别使用不同的聚合函数
- 分组后使用自定义聚合函数
- 分组转换聚合
- 分组后指定列数据转换聚合
- 分组后使用自定义函数进行转换聚合
- 分组聚合和分组转换的区别
- 分组过滤
- 数据离散化(分箱)
- 总结
- 项目地址:
1.学习目标
-
知道Pandas分组聚合的使用方法
-
知道Pandas分组转换聚合的使用方法
-
知道Pandas分组过滤的使用方法
-
知道Pandas数据离散化分箱操作的使用方法
2.分组对象DataFrameGroupBy
数据准备
-
加载优衣库的销售数据集,包含了不同城市优衣库门店的所有产品类别的销售记录,数据字段说明如下
-
store_id 门店随机id
-
city 城市
-
channel 销售渠道 网购自提 门店购买
-
gender_group 客户性别 男女
-
age_group 客户年龄段
-
wkd_ind 购买发生的时间(周末,周间)
-
product 产品类别
-
customer 客户数量
-
revenue 销售金额
-
order 订单数量
-
quant 购买产品的数量
-
unit_cost 成本(制作+运营)
-
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
df.groupby分组函数返回分组对象
-
基于一列进行分组
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
# 基于顾客性别分组
gs = df.groupby(['gender_group'])
print(gs)
print(gs['city'])
-
基于多列进行分组
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
# 基于顾客性别、不同城市分组
gs2 = df.groupby(['gender_group', 'city'])
print(gs2)
-
返回的分组对象可以直接使用,或选择一列做聚合、转换、过滤操作;比如我们要计算不同性别、不同城市的顾客的平均销售金额
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
# 按性别、城市分组后,选择销售金额列,做平均数计算
print(df.groupby(['gender_group', 'city'])['revenue'].mean())
分组对象其他API
取出每组第一条或最后一条数据
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
gs2 = df.groupby(['gender_group', 'channel'])
# 取出每组第一条数据
print(gs2.first())
# 取出每组最后一条数据
print(gs2.last())
获取分组后每组的名称
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
gs2 = df.groupby(['gender_group', 'channel'])
print(gs2.grouper.result_index)
print(gs2.grouper.result_index.tolist())
gs.get_group()
按分组依据获取其中一组
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
gs2 = df.groupby(['gender_group', 'channel'])
print(gs2.get_group(('Female', '线上')))
3.分组聚合
分组后直接聚合
- 分组后直接进行聚合计算并返回df
df.groupby(['列名1', '列名2']).聚合函数()
-
按性别分组,计算每组的各数值列的平均值
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
print(df.groupby(['gender_group'])[['store_id', 'customer', 'revenue', 'order', 'quant', 'unit_cost']].mean())
分组后指定单列或多列聚合
- 根据1列或多列的值进行分组,后每一组都对指定列的值使用聚合函数(比如mean求平均值)进行计算;分组后指定1列返回series对象,指定多列返回dataframe对象
df.groupby(['列名1', '列名2'])['指定列1'].聚合函数()
df.groupby(['列名1', '列名2'])['指定列1', '指定列2'].聚合函数()
-
计算不同城市的销售额总和
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
print(df.groupby(['city'])['revenue'].sum())
分组后使用多个聚合函数
- 同时使用多个内置聚合函数,全部放入一个Python列表, 然后把整个列表传入agg或aggregate函数中;返回以分组列作为索引,每一个聚合计算结果作为列的全新df
df.groupby(['列名1', '列名2'])['指定列1', '指定列2'].agg(['max', 'min'])
# max, min 为pandas内置的聚合函数名
-
按城市和线上线下划分,计算销售金额、成本的总和和平均值
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
print(df.groupby(['city', 'channel'])[['revenue', 'unit_cost']].agg(['sum', 'mean']))
分组后对多列分别使用不同的聚合函数
agg
函数中可以传入字典,字典的key是df的列名,与key对应的value是pandas内置的聚合计算函数、其名称的字符串;;返回以分组列作为索引,每一个聚合计算结果作为列的全新df
df.groupby(['列名1', '列名2']).agg({
'指定列1':'mean',
'指定列2':'sum',
'指定列3':'mean'
})
-
按城市和线上线下划分,分别计算销售金额的平均值、成本的总和
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
print(df.groupby(['city', 'channel']).agg({
'revenue': 'mean',
'unit_cost': 'sum'
}))
分组后使用自定义聚合函数
- 分组之后指定列,对该列的值使用自定义的函数;返回series对象
def bar(s, args1, args2):
'''自定义函数
s,为传入的series对象
args1,args2为自定义传参
'''
s_mean = s.sum() / s.size
return s_mean + args1 + args2
# 调用自定义函数
df.groupby(['列名1', '列名2']).agg(bar, args1=xxx, args2=xxx)
df.groupby(['列名1', '列名2'])['指定列1', '指定列2'].agg(bar, args1=xxx, args2=xxx)
-
按线上线下及不同城市划分,计算每组销售金额、成本的平均值,要求使用自定义聚合函数
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
def foo(s):
# 参数s 是分组之后指定的每一列
s_mean = s.sum() / s.size
return s_mean
print(df.groupby(['channel', 'city'])[['revenue', 'unit_cost']].agg(foo))
# 与下面的代码效果相同
# print(df.groupby(['channel', 'city'])[['revenue', 'unit_cost']].mean())
4.分组转换聚合
分组后指定列数据转换聚合
- 分组后,对指定列的值做聚合计算,只返回计算结果,不返回分组情况
df.groupby(['列名1', '列名2'])[['指定列1', '指定列2']].transform('sum') # sum是pandas内置聚合函数的函数名,求和
-
根据城市、性别分组,再计算每组销售金额、成本的平均值
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
print(df.groupby(['city', 'gender_group'])[['revenue', 'unit_cost']].transform('mean'))
分组后使用自定义函数进行转换聚合
- transform使用自定义的函数,注意此时传入的函数名没有引号
# 自定义一个计算函数
def foo(x, y):
return x + y
df.groupby('列名1')['列名2'].transform(foo, y=3)
-
根据城市、性别分组,再计算每组销售金额、成本的平均值;要求使用自定义函数
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
def foo(s):
return s.sum() / s.size
print(df.groupby(['city', 'gender_group'])[['revenue', 'unit_cost']].transform(foo))
分组聚合和分组转换的区别
- 二者返回对象的长度不同
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
print(df.groupby('city')['revenue'].transform('mean'))
print(df.groupby('city')['revenue'].mean())
# 前者返回结果的数据数量对应df的所有行,一一对应
# 后者返回的结果数据仅对应分组的个数
# 二者返回结果的长度不同
5.分组过滤
- 分组后接filter方法,filter传入一个返回布尔值的匿名函数,该函数的入参就是groupby分组之后的每一组数据或是每组选中的一列数据,返回False的数据会被过滤掉
df.groupby(['列名1',...]).filter(
lambda x: dosomething returun True or False
)
-
按城市分组,查询每组销售金额平均值大于200的全部数据,并获取索引值
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
print(df.groupby(['city']).filter(lambda s: s['revenue'].mean() > 200))
# df.groupby(['city']).filter(lambda s: s['revenue'].mean() > 200).index.tolist()
print(df.groupby(['city'])['revenue'].filter(lambda s: s.mean() > 200))
# df.groupby(['city'])['revenue'].filter(lambda s: s.mean() > 200).index.tolist()
6.数据离散化(分箱)
pd.cut()
函数用来把一组数据分割成离散的区间。比如有一组年龄数据,可以使用pandas.cut
将年龄数据分割成不同的年龄段并打上标签。上述过程又叫做分箱
pd.cut(x=Seriers对象, bins=3, labels=['低', '中', '高'])
-
离散化分箱函数的常用参数有:
-
x 指定离散化(分箱)依据的列,Seriers对象
-
bins 分为几组,int类型,也可以传入分组区间的列表
-
labels 每组的标签名称,按数值由小到大的顺序
-
right 默认True:左开右闭;False:左闭右开
-
include_lowest 默认False:不包含第一个分组的起始值;True:包含
-
-
按成本金额大小分为3组,将每条数据都打上高中低的标签
import pandas as pd
df = pd.read_csv('../datas/data_set/uniqlo.csv')
print(df)
# 复制数据集
df2 = df.copy()
# 分箱返回Seriers对象并复制给新的列
df2['成本高中低'] = pd.cut(x=df['unit_cost'], bins=3, labels=['低', '中', '高'])
# df2['成本高中低'] = pd.cut(x=df['unit_cost'], bins=[-1,20,50,999], labels=['低', '中', '高'])
# 查看数据集
print(df2)
7.总结
-
分组对象
-
gs = df.groupby(['列1', '列2'])
按照列1、列2的值对数据集进行分组,返回分组对象 -
gs.first()
返回每组的第一条数据 -
gs.last()
返回每组的最后一条数据 -
gs.grouper.result_index
获取全部组名 -
gs.get_group((组名))
按照
-
-
分组聚合
-
分组后直接聚合
df.groupby(['列名1', '列名2']).聚合函数()
-
分组后指定单列或多列聚合
df.groupby(['列名1', '列名2'])['指定列'].聚合函数()
-
分组后使用多个聚合函数
df.groupby(['列名1', '列名2'])['指定列1', '指定列2'].agg(['max', 'min'])
-
分组后对多列分别使用不同的聚合函数
df.groupby(['列名1', '列名2']).agg({ '指定列1':'mean', '指定列2':'sum', '指定列3':'mean' })
-
分组后使用自定义聚合函数
def foo(s): # 参数s 是分组之后指定的每一列 s_mean = s.sum() / s.size return s_mean df.groupby(['列名1', '列名2'])['指定列1', '指定列2'].agg(foo)
-
-
分组转换
-
分组后指定列数据转换
df.groupby(['列名1', '列名2'])['指定列1', '指定列2'].transform('pandas内置聚合函数的函数名')
-
分组后使用自定义函数进行转换聚合
def foo(x, y): return x + y df.groupby('列名1')['列名2'].transform(foo, y=3)
-
-
分组聚合和分组转换的区别:二者返回结果的长度不同
-
分组转换返回结果的数据数量对应df的所有行,一一对应
-
分组聚合返回的结果数据仅对应分组的个数
-
-
分组过滤
# 匿名函数入参就是groupby分组之后的每一组数据或是每组选中的一列数据,返回False的数据会被过滤掉 df.groupby(['列名1',...]).filter( lambda x: dosomething returun True or False )
-
数据离散化(分箱)用来把一组数据分割成若干个离散的区间。比如有一组年龄数据,可以使用
pandas.cut
将年龄数据分割成不同的年龄段并打上标签。上述过程又叫做分箱。-
参数x 指定离散化(分箱)依据的列,Seriers对象
-
参数bins 分为几组,int类型,也可以传入分组区间的列表
-
参数labels 每组的标签名称,按数值由小到大的顺序
-
参数right 默认True:左开右闭;False:左闭右开
-
参数include_lowest 默认False:不包含第一个分组的起始值;True:包含
- pd.cut(x=Seriers对象, bins=3, labels=['低', '中', '高'])
- pd.cut(x=Seriers对象, bins=[0,10,20,999], labels=['低', '中', '高'])
-