对数据集进行分组并对各组应用一个函数(无论是聚合还是转换),是数据分析的重要环节。
在将数据集准备好之后,通常的任务是计算分组统计或生成透视表。
pandas提供灵活高效的groupby功能,能够以一种自然的方式对数据集进行切片、切块、摘要等操作。
关系型数据库和SQL能够流行的原因之一是其能够方便的对数据进行连接、过滤、转换和聚合。
但实际上,SQL的分组运算能力有限。
GroupBy
粉组件可以有多种形式:
列表或数组,其长度与待分组的轴一样
表示DataFrame某个列名的值
字典或Series,给出待分组轴上的值与分组名之间的对应关系
函数,用于处理轴索引或索引中的各个标签
注意,后三种只是快捷方式而已,它们的最终目的都是产生一组用于拆分对象的值。
df = DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)})
按key1进行分组,并计算data1列的平均值
grouped = df['data1'].groupby(df['key1'])
变量grouped是一个GroupBy对象,计算平均值
grouped.mean()
key1
a 0.746672
b -0.537585
Name: data1, dtype: float64
数据根据粉组件产生聚合,并产生新的Series,其索引为key1列的唯一值。
如果我们一次传入多个数组,则得到不同的结果
means = df['data1'].groupby([df['key1'], df['key2']]).mean()
key1 key2
a one 0.880536
two 0.478943
b one -0.519439
two -0.555730
Name: data1, dtype: float64
上面通过两个键对数据进行分组,得到Series具有一个层次化索引,由唯一的键对组成。
对层次化索引升维
means.unstack()
key2 one two
key1
a 0.880536 0.478943
b -0.519439 -0.555730
在上面示例,分组键都是Series,实际上,分组键可以是任何长度适当的数组
states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])
years = np.array([2005, 2005, 2006, 2005, 2006])
df['data1'].groupby([states, years]).mean()
California 2005 0.478943
2006 -0.519439
Ohio 2005 -0.380219
2006 1.965781
Name: data1, dtype: float64
或者是将列名(可以是字符串、数字或其他Python对象)用作分组键
df.groupby('key1').mean()
data1 data2
key1
a 0.746672 0.910916
b -0.537585 0.525384
可以看到在执行上述操作后,结果中没有key2列。因为df['key2']不是数值数据(“麻烦列”),因此从结果中排除。
df.groupby(['key1', 'key2']).mean()
data1 data2
key1 key2
a one 0.880536 1.319920
two 0.478943 0.092908
b one -0.519439 0.281746
two -0.555730 0.769023
使用GroupBy的size方法,可以返回一个含有分组大小的Series
df.groupby(['key1', 'key2']).size()
key1 key2
a one 2
two 1
b one 1
two 1
dtype: int64