对数据集进行分组并对各组应用一个函数,这是数据分析的一个重要环节,将数据集准备好后,接下来的任务就是计算分组统计或深成透视表
GroupBy技术(分组)
创建一个GroupBy对象,再调用GroupBy的各种方法计算相关数据
df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)})
grouped = df['data1'].groupby(df['key1']) #先访问data1,再根据key1调用groupby
(df.groupby(xxx)) #创建一个GroupBy对象
grouped.mean()
grouped.size()
# groupby的参数是分组的键,分组键可以是Series,也可以是任何长度适当的数组,也可以是DataFrame的列名
df.groupby(df['key1'])
#以Series为分组键
states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])
years = np.array([2005, 2005, 2006, 2005, 2006])
df['data1'].groupby([states, years]).mean()
#以任何长度的数组为分组键
df.groupby('key1')
#以DataFrame的列名为分组键
- 对分组(GroupBy对象)进行迭代
GroupBy支持迭代,返回的一组二元元组:分组名+数据块
>>>for name, group in df.groupby('key1'):
print(name)
print(group)
a
key1 key2 data1 data2
0 a one -1.676303 -0.424336
1 a two 0.043207 -0.172227
4 a one -0.165924 -0.145246
b
key1 key2 data1 data2
2 b one 1.449175 0.155494
3 b two -0.379370 -0.075793
对数据片段做任何操作:将这些数据片段做成一个字典
pieces = dict(list(df.groupby('key1'))) #list既将刚刚打印的东西作为一个列表,dict是将打印的name作为key,将group作为value
- 选取一个或一组列
> 对于由DataFrame产生的GroupBy对象,如果用一个或一组列名对其进行索引,就能实现选取部分列进行聚合的目的
df.groupby(['key1', 'key2'])[['data2','data1']].mean()
#以一个数组作为索引,返回的是DataFrame
df.groupby(['key1', 'key2'])['data2'].mean()
#以单个列名作为索引,返回的是Series
- 通过Series或字典进行GroupBy
> 通过字典或Series给列名分组,然后再根据新分的组GroupBy
mapping = {'a': 'red', 'b': 'red', 'c': 'blue',
'd': 'blue', 'e': 'red', 'f' : 'orange'}
by_column = people.groupby(mapping, axis=1)
by_column.sum()
map_series = pd.Series(mapping)
map_series
people.groupby(map_series, axis=1).count() #以Series作为分组键
- 通过函数进行分组
函数作为分组键的传入,则该函数会在各个***索引值***上被调用一次,其返回值都会被用作分组名称
people.groupby(len).sum() #按人名长度进行分组,直接传入函数名称,不用带(),也不用带参数
# 将函数和数组、列表、字典、Series混合使用也不是问题
key_list = ['one', 'one', 'one', 'two', 'two']
people.groupby([len, key_list]).sum()
- 根据索引级别分组
用level关键字传入级别编号,用axis=1对竖向GroupBy
hier_df.groupby(level='cty', axis=1).count()
数据聚合
# 直接使用groupby内含的方法
>>> grouped['data1'].quantile(0.9)
>>> grouped.describe()
# 使用自己的聚合函数,将函数名称传入aggregate或agg方法即可:
>>> def peak_to_peak(arr):
return arr.max() - arr.min()
>>> grouped.agg(peak_to_peak)
# 经过优化的GroupBy的方法
count #分组中非NA值的数量
sum #非NA值的和
mean #非NA值的平均数
median #非NA值的算术中位数
std\var #无偏(分母n-1)标准差和方差
min\max #非NA值的最小值和最大值
prod #非NA值的积
first\last #第一个和最后一个非NA值
- 面向列的多函数应用
对不同的列使用不同的聚合函数,或一次应用多个函数
# 传入一组函数或函数名,得到的DataFrame的列就会以相应的函数命名
>>> grouped_pct.agg(['mean', 'std', peak_to_peak])
>>> grouped_pct.agg([('foo', 'mean'), ('bar', np.std)])
#由(name, function)元组组成的列表作为参数传入,各元组的第一个元素会被用作DataFrame的列名
# 应用多个函数,将函数以列表形式传入
>>> functions = ['count', 'mean', 'max']
>>> result = grouped['tip_pct', 'total_bill'].agg(functions)
# 对不同的列应用不同的函数,向agg传入一个从列名映射到函数的字典
>>> grouped.agg({'tip_pct' : ['min', 'max', 'mean', 'std'], 'size' : 'sum'})
- 以“无索引”的形式返回聚合函数:分组键不作为索引
grouped = tips.groupby(['day', 'smoker'], as_index=False) #day和smoker不作为返回的dataframe的索引
分组级运算和转换
聚合知识分组运算的一种而已,它接受能够将一维数组简化为标量值的函数。
将介绍transform和apply方法,能够执行更多其他的分组运算