如何使用熊猫进行聚合?
聚合后没有DataFrame!发生什么了?
如何主要汇总字符串列(到
list
,tuple
,strings with separator
)?如何汇总计数?
如何创建由汇总值填充的新列?
>
我已经看到这些重复出现的问题,它们询问熊猫聚合功能的各个方面。
如今,有关汇总及其各种用例的大多数信息都分散在数十个措辞不好,无法搜索的帖子中。
这里的目的是整理一些更重要的要点。
此问题解答是一系列有用的用户指南的下一部分:
如何旋转数据框,
Pandas concat
我如何在每个列上使用带有系列的数据框
Pandas合并101
请注意,本文并非旨在代替有关聚合和groupby的文档,因此也请阅读!
#1 楼
问题1如何使用熊猫执行聚合?
扩展了聚合文档。
聚合函数是减小返回对象尺寸的函数。这意味着输出Series / DataFrame与原始行相比具有更少或相同的行。
一些常用的聚合函数列表如下:
Function Description mean() Compute mean of groups sum() Compute sum of group values size() Compute group sizes count() Compute count of group std() Standard deviation of groups var() Compute variance of groups sem() Standard error of the mean of groups describe() Generates descriptive statistics first() Compute first of group values last() Compute last of group values nth() Take nth value, or a subset if n is a list min() Compute min of group values max() Compute max of group values
np.random.seed(123)
df = pd.DataFrame({'A' : ['foo', 'foo', 'bar', 'foo', 'bar', 'foo'],
'B' : ['one', 'two', 'three','two', 'two', 'one'],
'C' : np.random.randint(5, size=6),
'D' : np.random.randint(5, size=6),
'E' : np.random.randint(5, size=6)})
print (df)
A B C D E
0 foo one 2 3 0
1 foo two 4 1 0
2 bar three 2 1 1
3 foo two 1 0 3
4 bar two 3 1 4
5 foo one 2 1 0
通过过滤列和cython实现的函数进行的聚合:
df1 = df.groupby(['A', 'B'], as_index=False)['C'].sum()
print (df1)
A B C
0 bar three 2
1 bar two 3
2 foo one 4
3 foo two 5
所有未在
groupby
函数中指定的列均使用聚合函数,此处A, B
列:df2 = df.groupby(['A', 'B'], as_index=False).sum()
print (df2)
A B C D E
0 bar three 2 1 1
1 bar two 3 1 4
2 foo one 4 4 0
3 foo two 5 1 3
在
groupby
函数之后,您也可以仅在列表中指定一些用于聚合的列:df3 = df.groupby(['A', 'B'], as_index=False)['C','D'].sum()
print (df3)
A B C D
0 bar three 2 1
1 bar two 3 1
2 foo one 4 4
3 foo two 5 1
使用函数
DataFrameGroupBy.agg
的结果相同:df1 = df.groupby(['A', 'B'], as_index=False)['C'].agg('sum')
print (df1)
A B C
0 bar three 2
1 bar two 3
2 foo one 4
3 foo two 5
df2 = df.groupby(['A', 'B'], as_index=False).agg('sum')
print (df2)
A B C D E
0 bar three 2 1 1
1 bar two 3 1 4
2 foo one 4 4 0
3 foo two 5 1 3
对于应用于一列的多个函数,请使用
tuple
的列表-新列的名称和聚合函数:df4 = (df.groupby(['A', 'B'])['C']
.agg([('average','mean'),('total','sum')])
.reset_index())
print (df4)
A B average total
0 bar three 2.0 2
1 bar two 3.0 3
2 foo one 2.0 4
3 foo two 2.5 5
如果可能要传递多个功能,请传递
list
的tuple
s:df5 = (df.groupby(['A', 'B'])
.agg([('average','mean'),('total','sum')]))
print (df5)
C D E
average total average total average total
A B
bar three 2.0 2 1.0 1 1.0 1
two 3.0 3 1.0 1 4.0 4
foo one 2.0 4 2.0 4 0.0 0
two 2.5 5 0.5 1 1.5 3
然后在列中获取
MultiIndex
:print (df5.columns)
MultiIndex(levels=[['C', 'D', 'E'], ['average', 'total']],
labels=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])
并转换为列,将
MultiIndex
展平,将map
与join
结合使用:df5.columns = df5.columns.map('_'.join)
df5 = df5.reset_index()
print (df5)
A B C_average C_total D_average D_total E_average E_total
0 bar three 2.0 2 1.0 1 1.0 1
1 bar two 3.0 3 1.0 1 4.0 4
2 foo one 2.0 4 2.0 4 0.0 0
3 foo two 2.5 5 0.5 1 1.5 3
另一个解决方案是传递聚合函数列表,然后将
MultiIndex
展平,对于其他列名称,请使用str.replace
:df5 = df.groupby(['A', 'B']).agg(['mean','sum'])
df5.columns = (df5.columns.map('_'.join)
.str.replace('sum','total')
.str.replace('mean','average'))
df5 = df5.reset_index()
print (df5)
A B C_average C_total D_average D_total E_average E_total
0 bar three 2.0 2 1.0 1 1.0 1
1 bar two 3.0 3 1.0 1 4.0 4
2 foo one 2.0 4 2.0 4 0.0 0
3 foo two 2.5 5 0.5 1 1.5 3
如果要指定每个具有聚合函数的列,则分别传递
dictionary
:df6 = (df.groupby(['A', 'B'], as_index=False)
.agg({'C':'sum','D':'mean'})
.rename(columns={'C':'C_total', 'D':'D_average'}))
print (df6)
A B C_total D_average
0 bar three 2 1.0
1 bar two 3 1.0
2 foo one 4 2.0
3 foo two 5 0.5
也可以通过自定义函数:
def func(x):
return x.iat[0] + x.iat[-1]
df7 = (df.groupby(['A', 'B'], as_index=False)
.agg({'C':'sum','D': func})
.rename(columns={'C':'C_total', 'D':'D_sum_first_and_last'}))
print (df7)
A B C_total D_sum_first_and_last
0 bar three 2 2
1 bar two 3 2
2 foo one 4 4
3 foo two 5 1
问题2
聚合后没有DataFrame!
通过2列或更多列进行汇总:
df1 = df.groupby(['A', 'B'])['C'].sum()
print (df1)
A B
bar three 2
two 3
foo one 4
two 5
Name: C, dtype: int32
首先检查pandas对象的
Index
和type
:print (df1.index)
MultiIndex(levels=[['bar', 'foo'], ['one', 'three', 'two']],
labels=[[0, 0, 1, 1], [1, 2, 0, 2]],
names=['A', 'B'])
print (type(df1))
<class 'pandas.core.series.Series'>
有2种解决方案如何将
MultiIndex Series
转换为列:添加参数
as_index=False
df1 = df.groupby(['A', 'B'], as_index=False)['C'].sum()
print (df1)
A B C
0 bar three 2
1 bar two 3
2 foo one 4
3 foo two 5
使用
Series.reset_index
:df1 = df.groupby(['A', 'B'])['C'].sum().reset_index()
print (df1)
A B C
0 bar three 2
1 bar two 3
2 foo one 4
3 foo two 5
如果按一列分组:
df2 = df.groupby('A')['C'].sum()
print (df2)
A
bar 5
foo 9
Name: C, dtype: int32
...得到带有
Series
的Index
:print (df2.index)
Index(['bar', 'foo'], dtype='object', name='A')
print (type(df2))
<class 'pandas.core.series.Series'>
和解决方案就像在
MultiIndex Series
中一样:df2 = df.groupby('A', as_index=False)['C'].sum()
print (df2)
A C
0 bar 5
1 foo 9
df2 = df.groupby('A')['C'].sum().reset_index()
print (df2)
A C
0 bar 5
1 foo 9
问题3
如何主要汇总字符串列(到
list
,tuple
s,strings with separator
)?df = pd.DataFrame({'A' : ['a', 'c', 'b', 'b', 'a', 'c', 'b'],
'B' : ['one', 'two', 'three','two', 'two', 'one', 'three'],
'C' : ['three', 'one', 'two', 'two', 'three','two', 'one'],
'D' : [1,2,3,2,3,1,2]})
print (df)
A B C D
0 a one three 1
1 c two one 2
2 b three two 3
3 b two two 2
4 a two three 3
5 c one two 1
6 b three one 2
聚集函数的函数可以传递
list
,tuple
和set
来转换列:df1 = df.groupby('A')['B'].agg(list).reset_index()
print (df1)
A B
0 a [one, two]
1 b [three, two, three]
2 c [two, one]
也可以使用
GroupBy.apply
:df1 = df.groupby('A')['B'].apply(list).reset_index()
print (df1)
A B
0 a [one, two]
1 b [three, two, three]
2 c [two, one]
要转换为带分隔符的字符串,请仅使用
.join
如果字符串列:df2 = df.groupby('A')['B'].agg(','.join).reset_index()
print (df2)
A B
0 a one,two
1 b three,two,three
2 c two,one
如果数字列使用带
astype
的lambda函数转换为string
s:df3 = (df.groupby('A')['D']
.agg(lambda x: ','.join(x.astype(str)))
.reset_index())
print (df3)
A D
0 a 1,3
1 b 3,2,2
2 c 2,1
另一种解决方案是将
groupby
转换为字符串:df3 = (df.assign(D = df['D'].astype(str))
.groupby('A')['D']
.agg(','.join).reset_index())
print (df3)
A D
0 a 1,3
1 b 3,2,2
2 c 2,1
要转换所有列,请不要在
groupby
之后传递任何列的列表。没有列
D
是因为自动排除了“讨厌的”列,这意味着所有数字列均被排除。 br /> df4 = df.groupby('A').agg(','.join).reset_index()
print (df4)
A B C
0 a one,two three,three
1 b three,two,three two,two,one
2 c two,one one,two
因此有必要将所有列转换为字符串,然后获取所有列:
df5 = (df.groupby('A')
.agg(lambda x: ','.join(x.astype(str)))
.reset_index())
print (df5)
A B C D
0 a one,two three,three 1,3
1 b three,two,three two,two,one 3,2,2
2 c two,one one,two 2,1
问题4
如何汇总计数?
df = pd.DataFrame({'A' : ['a', 'c', 'b', 'b', 'a', 'c', 'b'],
'B' : ['one', 'two', 'three','two', 'two', 'one', 'three'],
'C' : ['three', np.nan, np.nan, 'two', 'three','two', 'one'],
'D' : [np.nan,2,3,2,3,np.nan,2]})
print (df)
A B C D
0 a one three NaN
1 c two NaN 2.0
2 b three NaN 3.0
3 b two two 2.0
4 a two three 3.0
5 c one two NaN
6 b three one 2.0
每组
GroupBy.size
的功能size
:df1 = df.groupby('A').size().reset_index(name='COUNT')
print (df1)
A COUNT
0 a 2
1 b 3
2 c 2
函数
GroupBy.count
排除缺失值:df2 = df.groupby('A')['C'].count().reset_index(name='COUNT')
print (df2)
A COUNT
0 a 2
1 b 2
2 c 1
应在多个列中使用此函数来计数不丢失的值:
df3 = df.groupby('A').count().add_suffix('_COUNT').reset_index()
print (df3)
A B_COUNT C_COUNT D_COUNT
0 a 2 2 1
1 b 3 2 3
2 c 2 1 1
相关函数
Series.value_counts
返回大小的对象包含按降序排列的唯一值,因此第一个元素是最频繁出现的元素。默认情况下不包括
NaN
的值。df4 = (df['A'].value_counts()
.rename_axis('A')
.reset_index(name='COUNT'))
print (df4)
A COUNT
0 b 3
1 a 2
2 c 2
如果要使用函数
groupby
+ size
进行相同的输出,请添加Series.sort_index
:df5 = (df['A'].value_counts()
.sort_index()
.rename_axis('A')
.reset_index(name='COUNT'))
print (df5)
A COUNT
0 a 2
1 b 3
2 c 2
问题5
如何创建新列
方法
GroupBy.transform
返回的索引与被分组的对象相同(大小相同)熊猫文档以获取更多信息。
np.random.seed(123)
df = pd.DataFrame({'A' : ['foo', 'foo', 'bar', 'foo', 'bar', 'foo'],
'B' : ['one', 'two', 'three','two', 'two', 'one'],
'C' : np.random.randint(5, size=6),
'D' : np.random.randint(5, size=6)})
print (df)
A B C D
0 foo one 2 3
1 foo two 4 1
2 bar three 2 1
3 foo two 1 0
4 bar two 3 1
5 foo one 2 1
df['C1'] = df.groupby('A')['C'].transform('sum')
df['C2'] = df.groupby(['A','B'])['C'].transform('sum')
df[['C3','D3']] = df.groupby('A')['C','D'].transform('sum')
df[['C4','D4']] = df.groupby(['A','B'])['C','D'].transform('sum')
print (df)
A B C D C1 C2 C3 D3 C4 D4
0 foo one 2 3 9 4 9 5 4 4
1 foo two 4 1 9 5 9 5 5 1
2 bar three 2 1 5 2 5 2 2 1
3 foo two 1 0 9 5 9 5 5 1
4 bar two 3 1 5 3 5 2 3 1
5 foo one 2 1 9 4 9 5 4 4
评论
@AbhishekDujari-我尝试使用有关聚合的一些相关问题来扩展文档,因此像文档中那样有更多信息。
– Jezrael
18/12/14在14:52
谢谢。尽管我建议为项目本身做贡献。这些出色的例子将使很多学生受益
– Abhishek Dujari
18/12/16在8:16
可用的聚合功能列表...您在哪里找到它?我似乎无法在官方文档中的任何地方找到它!谢谢!
–QA集体
11月18日,0:37
@QACollective-您可以检查此
– Jezrael
11月18日4:59
@jezrael您能帮我解决这个问题stackoverflow.com/questions/65252632 / ...
– Azucode
12月11日17:19
#2 楼
如果您来自R或SQL背景,这里有3个示例,这些示例将教您以熟悉的方式进行聚合所需的一切:让我们首先创建一个Pandas数据框。
import pandas as pd
df = pd.DataFrame({'key1' : ['a','a','a','b','a'],
'key2' : ['c','c','d','d','e'],
'value1' : [1,2,2,3,3],
'value2' : [9,8,7,6,5]})
df.head(5)
以下是我们创建的表格的外观:
|----------------|-------------|------------|------------|
| key1 | key2 | value1 | value2 |
|----------------|-------------|------------|------------|
| a | c | 1 | 9 |
| a | c | 2 | 8 |
| a | d | 2 | 7 |
| b | d | 3 | 6 |
| a | e | 3 | 5 |
|----------------|-------------|------------|------------|
1。通过行减少进行聚合类似于SQL
Group By
df_agg = df.groupby(['key1','key2']).agg(mean_of_value_1=('value1', 'mean'),
sum_of_value_2=('value2', 'sum'),
count_of_value1=('value1','size')
).reset_index()
df_agg.head(5)
结果数据表将如下所示:
|----------------|-------------|--------------------|-------------------|---------------------|
| key1 | key2 | mean_of_value1 | sum_of_value2 | count_of_value1 |
|----------------|-------------|--------------------|-------------------|---------------------|
| a | c | 1.5 | 17 | 2 |
| a | d | 2.0 | 7 | 1 |
| a | e | 3.0 | 5 | 1 |
| b | d | 3.0 | 6 | 1 |
|----------------|-------------|--------------------|-------------------|---------------------|
SQL的等效项是:
SELECT
key1
,key2
,AVG(value1) AS mean_of_value_1
,SUM(value2) AS sum_of_value_2
,COUNT(*) AS count_of_value1
FROM
df
GROUP BY
key1
,key2
2。创建列时不减少行数(
EXCEL - SUMIF, COUNTIF
)如果要进行SUMIF,COUNTIF等操作,就像在不减少行数的Excel中的操作一样,则需要执行此操作。
df['Total_of_value1_by_key1'] = df.groupby('key1')['value1'].transform('sum')
df.head(5)
结果数据帧将具有与原始行相同的行数:
|----------------|-------------|------------|------------|-------------------------|
| key1 | key2 | value1 | value2 | Total_of_value1_by_key1 |
|----------------|-------------|------------|------------|-------------------------|
| a | c | 1 | 9 | 8 |
| a | c | 2 | 8 | 8 |
| a | d | 2 | 7 | 8 |
| b | d | 3 | 6 | 3 |
| a | e | 3 | 5 | 8 |
|----------------|-------------|------------|------------|-------------------------|
3。创建一个RANK列
ROW_NUMBER() OVER (PARTITION BY ORDER BY)
最后,在某些情况下,您可能想创建一个与SQL等效的
ROW_NUMBER() OVER (PARTITION BY key1 ORDER BY value1 DESC, value2 ASC)
的Rank列,这是您的操作方法。 df['RN'] = df.sort_values(['value1','value2'], ascending=[False,True]) \
.groupby(['key1']) \
.cumcount() + 1
df.head(5)
注意:我们通过在每行的末尾添加
\
来使代码成为多行代码。这是结果数据帧的样子:
|----------------|-------------|------------|------------|------------|
| key1 | key2 | value1 | value2 | RN |
|----------------|-------------|------------|------------|------------|
| a | c | 1 | 9 | 4 |
| a | c | 2 | 8 | 3 |
| a | d | 2 | 7 | 2 |
| b | d | 3 | 6 | 1 |
| a | e | 3 | 5 | 1 |
|----------------|-------------|------------|------------|------------|
在所有示例中上面的数据,最终的数据表将具有表结构,并且不会具有其他语法中可能具有的枢轴结构。
其他聚合运算符:
mean()
计算组的均值sum()
计算组值之和size()
计算组大小count()
计算组数std()
组的标准差var()
计算组的方差sem()
均值的标准误差组describe()
生成描述性统计信息first()
计算组值的第一个last()
计算组值的最后一个nth()
取第n个值,如果n是一个列表,则取一个子集min()
计算组值的最小值max()
计算组值的最大值希望有帮助。
评论
当df有Nan时,这成立吗?
–盖德
9月26日上午11:57
评论
您能帮我解决这个问题吗stackoverflow.com/questions/65252632 / ...