【问题标题】:Pandas: aggregate based on filter on another columnPandas:基于另一列上的过滤器进行聚合
【发布时间】:2017-02-02 21:26:39
【问题描述】:

我有一个看起来像这样的数据框

Month   Fruit   Sales
1       Apple   45
1       Bananas 12
3       Apple   6
1       Kiwi    34
12      Melon   12

我正在尝试获取这样的数据框

Fruit         Sales (month=1)     Sales (month=2)
Apple         55                  65
Bananas       12                  102
Kiwi          54                  78
Melon         132                 43

我现在有

df=df.groupby(['Fruit']).agg({'Sales':np.sum}).reset_index()

必须有一些方法可以根据“月份”变量过滤 agg() 中的参数。我只是无法在文档中找到它。有什么帮助吗?

编辑: 感谢您的解决方案。为了使事情复杂化,我还想总结另一列。示例:

Month    Fruit    Sales  Revenue
1       Apple    45     45
1       Bananas  12     12
3       Apple    6      6
1       Kiwi     34     34
12      Melon    12     12

首选输出类似于

            Sales      Revenue
     Fruit   1  3  12  1   3  12
0    Apple  61  6   0  61  6  0
1  Bananas  12  6   0  12  6  0
2     Kiwi  34  0   0  34  0  0
3    Melon   0  0  12  0   0  12

我设法通过df.pivot_table(values=['Sales','Revenue'], index='Fruit', columns=['Month'], aggfunc='np.sum').reset_index() 解决了这个问题。

我对@9​​87654327@ 尝试了同样的操作,但这会引发 TypeError。 groupby也可以进行上述操作吗?

【问题讨论】:

  • 这不是 SO 的工作方式,请向我们展示您迄今为止共同完成的 sn-p。

标签: python pandas aggregate


【解决方案1】:

要回答更新后的问题,您应该做一些不同的事情。 首先group by 后面应该是列的元素(月份和水果)。然后计算这些组的总和,然后计算unstack DataFrame,将 Fruit 列作为索引列。

data = '''
Month    Fruit   Sales  Revenue
1       Apple    45     45
1       Bananas  12     12
1       Apple    16     16
3       Apple    6      6
1       Kiwi     34     34
3       Bananas  6      6
12      Melon    12     12
'''
df = pd.read_csv(StringIO(data), sep='\s+')

df.groupby(['Month', 'Fruit'])\
    .sum()\
    .unstack(level=0)

结果

        Sales            Revenue           
Month      1    3     12      1    3     12
Fruit                                      
Apple    61.0  6.0   NaN    61.0  6.0   NaN
Bananas  12.0  6.0   NaN    12.0  6.0   NaN
Kiwi     34.0  NaN   NaN    34.0  NaN   NaN
Melon     NaN  NaN  12.0     NaN  NaN  12.0

旧答案

使用pivot_table 方法:

import pandas as pd
from io import StringIO

data = '''\
Month Fruit  Sales
1       Apple   45
1       Bananas 12
1       Apple   16
3       Apple   6
1       Kiwi    34
3       Bananas 6
12      Melon   12
'''
df = pd.read_csv(StringIO(data), sep='\s+')

df.pivot_table('Sales', index='Fruit', columns=['Month'], aggfunc='sum')

结果:

Month      1    3     12
Fruit                   
Apple    61.0  6.0   NaN
Bananas  12.0  6.0   NaN
Kiwi     34.0  NaN   NaN
Melon     NaN  NaN  12.0

【讨论】:

    【解决方案2】:

    更新:

    In [177]: df
    Out[177]:
       Month    Fruit  Sales  Revenue
    0      1    Apple     45       45
    1      1  Bananas     12       12
    2      3    Apple      6        6
    3      1     Kiwi     34       34
    4     12    Melon     12       12
    
    In [178]: df.groupby(['Fruit', 'Month'])[['Sales','Revenue']].sum().unstack('Month', fill_value=0)
    Out[178]:
            Sales        Revenue
    Month      1  3   12      1  3   12
    Fruit
    Apple      45  6   0      45  6   0
    Bananas    12  0   0      12  0   0
    Kiwi       34  0   0      34  0   0
    Melon       0  0  12       0  0  12
    

    旧答案:

    您也可以使用groupby() + unstack():

    In [206]: df.groupby(['Fruit', 'Month'])['Sales'].sum().unstack('Month', fill_value=0) \
         ...:   .rename_axis(None, 1).reset_index()
         ...:
    Out[206]:
         Fruit   1  3  12
    0    Apple  61  6   0
    1  Bananas  12  6   0
    2     Kiwi  34  0   0
    3    Melon   0  0  12
    

    【讨论】:

    • 感谢您的解决方案。一个问题。假设我有一个“销售”和“收入”列,我希望对它们进行总结。我设法使用带有参数values=['Sales','Revenue'] 的pivot_table 使其工作。但是,当我使用 unstack() 尝试此操作时,它会给出错误TypeError: Must pass list-like as names。 unstack() 函数不适合做这样的操作吗?
    • @Duudsrednaz,能否提供可重现的样本数据集和所需的数据集?
    • 是的,我已经更新了第一篇文章。我只是想知道是否 pivot_table 或 groupby 更适合这个。
    • @Duudsrednaz,我已经更新了我的答案 - 这就是你想要的吗?
    • 就是这样,谢谢。我看到rename_axis 导致了 TypeError,但我不知道为什么。你能帮我理解为什么第一个例子需要rename_axis,而不是最后一个吗?
    猜你喜欢
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多