我该如何使用Pandas进行分组并获取总和?

385

我正在使用这个数据框:

Fruit   Date      Name  Number
Apples  10/6/2016 Bob    7
Apples  10/6/2016 Bob    8
Apples  10/6/2016 Mike   9
Apples  10/7/2016 Steve 10
Apples  10/7/2016 Bob    1
Oranges 10/7/2016 Bob    2
Oranges 10/6/2016 Tom   15
Oranges 10/6/2016 Mike  57
Oranges 10/6/2016 Bob   65
Oranges 10/7/2016 Tony   1
Grapes  10/7/2016 Bob    1
Grapes  10/7/2016 Tom   87
Grapes  10/7/2016 Bob   22
Grapes  10/7/2016 Bob   12
Grapes  10/7/2016 Tony  15

我想按Name然后按Fruit汇总,以获得每个NameFruit总数。例如:

Bob,Apples,16

我尝试按照NameFruit进行分组,但是如何获得所有Fruit的总数呢?


2
你可以使用dfsql df.sql('SELECT fruit, sum(number) GROUP BY fruit')。https://github.com/mindsdb/dfsqlhttps://medium.com/riselab/why-every-data-scientist-using-pandas-needs-modin-bringing-sql-to-dataframes-3b216b29a7c0 - Jorge Torres
11个回答

440

使用GroupBy.sum函数:

df.groupby(['Fruit','Name']).sum()

Out[31]: 
               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Grapes  Bob        35
        Tom        87
        Tony       15
Oranges Bob        67
        Mike       57
        Tom        15
        Tony        1

要指定要求和的列,请使用此代码:df.groupby(['Name', 'Fruit'])['Number'].sum()


问题是,如果从Excel读取数据,并且当我们从Excel读取数据时,“Number”应该默认为字符串,那么如何使用sum()函数? - Rui

'overview.csv'文件中有五列数据

temp = pd.read_csv("overview.csv") temp.groupby([temp.columns[0],temp.columns[1]])[temp.columns[4]].sum()print(temp)无法得到'temp.columns[4]'的总和
- Rui

265

你也可以使用聚合函数(agg function)。

df.groupby(['Name', 'Fruit'])['Number'].agg('sum')

207

如果您想保留原始列 FruitName,请使用 reset_index()。否则 FruitName 将成为索引的一部分。

df.groupby(['Fruit','Name'])['Number'].sum().reset_index()

Fruit   Name       Number
Apples  Bob        16
Apples  Mike        9
Apples  Steve      10
Grapes  Bob        35
Grapes  Tom        87
Grapes  Tony       15
Oranges Bob        67
Oranges Mike       57
Oranges Tom        15
Oranges Tony        1

正如其他答案中所见:

df.groupby(['Fruit','Name'])['Number'].sum()

               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Grapes  Bob        35
        Tom        87
        Tony       15
Oranges Bob        67
        Mike       57
        Tom        15
        Tony        1

62

其他两个答案都可以实现你想要的功能。

你可以使用 pivot 功能将数据排列在一个漂亮的表中。

df.groupby(['Fruit','Name'],as_index = False).sum().pivot('Fruit','Name').fillna(0)



Name    Bob     Mike    Steve   Tom    Tony
Fruit                   
Apples  16.0    9.0     10.0    0.0     0.0
Grapes  35.0    0.0     0.0     87.0    15.0
Oranges 67.0    57.0    0.0     15.0    1.0

35
df.groupby(['Fruit','Name'])['Number'].sum()

您可以选择不同的列对数字进行求和。


24

一个 .agg() 函数的变体;提供以下功能:(1)持久化类型为DataFrame,(2)应用平均值、计数、求和等操作,(3)在保持易读性的情况下对多列进行分组。

df.groupby(['att1', 'att2']).agg({'att1': "count", 'att3': "sum",'att4': 'mean'})

运用您的价值观...

df.groupby(['Name', 'Fruit']).agg({'Number': "sum"})

12

您可以将 groupby 列设置为 index,然后使用带有 levelsum

df.set_index(['Fruit','Name']).sum(level=[0,1])
Out[175]: 
               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Oranges Bob        67
        Tom        15
        Mike       57
        Tony        1
Grapes  Bob        35
        Tom        87
        Tony       15

11
你也可以在分组之后在列Number上使用transform()。这个操作将使用函数sum计算一组中的总数,结果是一个与原始数据框具有相同索引的系列。
df['Number'] = df.groupby(['Fruit', 'Name'])['Number'].transform('sum')
df = df.drop_duplicates(subset=['Fruit', 'Name']).drop('Date', 1)

接下来,您可以在列FruitName上删除重复行。此外,您可以通过指定轴10表示行,1表示列)来删除列Date

# print(df)

      Fruit   Name  Number
0    Apples    Bob      16
2    Apples   Mike       9
3    Apples  Steve      10
5   Oranges    Bob      67
6   Oranges    Tom      15
7   Oranges   Mike      57
9   Oranges   Tony       1
10   Grapes    Bob      35
11   Grapes    Tom      87
14   Grapes   Tony      15

# You could achieve the same result with functions discussed by others: 
# print(df.groupby(['Fruit', 'Name'], as_index=False)['Number'].sum())
# print(df.groupby(['Fruit', 'Name'], as_index=False)['Number'].agg('sum'))

有一个官方教程Group by: split-apply-combine,讲述了在分组后可以做什么。


大家好,你们的解决方案确实有效!我的Python版本是3.8,如果我们只使用sum()函数,似乎它确实可以工作。 - Rui
@Rui 不理解,你只是说它能工作,那么什么情况下它不能工作? - Ynjxsjmh
Ynjxsjmh,我的意思是如果我只使用“df ['Number'] = df.groupby(['Fruit','Name'])['Number'].transform('sum')”,我无法获得按'Fruit','Name'对分组的'Number'总和。但是,如果我按照您的评论建议添加行“df = df.drop_duplicates(subset = ['Fruit','Name'])”,那么我就得到了预期的总和。 - Rui

3
如果您希望聚合列具有自定义名称,如“总数”、“总计”等(这里的所有解决方案都会导致聚合列命名为“Number”),请使用命名聚合:

如果你想让聚合列有一个自定义的名称,比如 "总数","总计"等(在这里的所有解决方案中,聚合列都被命名为 "Number"),使用命名聚合:
df.groupby(['Fruit', 'Name'], as_index=False).agg(**{'Total Number': ('Number', 'sum')})

或者(如果自定义名称不需要有空格):
df.groupby(['Fruit', 'Name'], as_index=False).agg(Total=('Number', 'sum'))

这相当于 SQL 查询:

SELECT Fruit, Name, sum(Number) AS Total
FROM df 
GROUP BY Fruit, Name

说到SQL,有一个名为pandasql的模块可以让你使用SQL语法在本地环境下查询pandas数据框中的数据。它不是Pandas的一部分,因此需要单独安装。

#! pip install pandasql
from pandasql import sqldf
sqldf("""
SELECT Fruit, Name, sum(Number) AS Total
FROM df 
GROUP BY Fruit, Name
""")

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接