如何使用熊猫进行聚合?
聚合后没有DataFrame!发生什么了?
如何主要汇总字符串列(到listtuplestrings with separator)?
如何汇总计数?
如何创建由汇总值填充的新列?
>
我已经看到这些重复出现的问题,它们询问熊猫聚合功能的各个方面。
如今,有关汇总及其各种用例的大多数信息都分散在数十个措辞不好,无法搜索的帖子中。
这里的目的是整理一些更重要的要点。

此问题解答是一系列有用的用户指南的下一部分:



如何旋转数据框,
Pandas concat
我如何在每个列上使用带有系列的数据框
Pandas合并101

请注意,本文并非旨在代替有关聚合和groupby的文档,因此也请阅读!

评论

您能帮我解决这个问题吗stackoverflow.com/questions/65252632 / ...

#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

如果可能要传递多个功能,请传递listtuple 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展平,将mapjoin结合使用:
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对象的Indextype
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

...得到带有SeriesIndex
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
如何主要汇总字符串列(到listtuple 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

聚集函数的函数可以传递listtupleset来转换列:
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