【问题标题】:Pandas: Transpose, groupby and summarize columnsPandas:转置、分组和汇总列
【发布时间】:2019-09-29 18:14:04
【问题描述】:

我有一个看起来像这样的 pandas DataFrame:

| Id | Filter 1 | Filter 2 | Filter 3 |
|----|----------|----------|----------|
| 25 | 0        | 1        | 1        |
| 25 | 1        | 0        | 1        |
| 25 | 0        | 0        | 1        |
| 30 | 1        | 0        | 1        |
| 31 | 1        | 0        | 1        |
| 31 | 0        | 1        | 0        |
| 31 | 0        | 0        | 1        |

我需要转置此表,添加带有过滤器名称的“名称”列并汇总过滤器列值。结果表应该是这样的:

| Id | Name     | Summ |
| 25 | Filter 1 | 1    |
| 25 | Filter 2 | 1    |
| 25 | Filter 3 | 3    |
| 30 | Filter 1 | 1    |
| 30 | Filter 2 | 0    |
| 30 | Filter 3 | 1    |
| 31 | Filter 1 | 1    |
| 31 | Filter 2 | 1    |
| 31 | Filter 3 | 2    |

到目前为止,我唯一的解决方案是在按 Id 列分组时使用 apply 函数,但这种方法对我的情况来说太慢了 - 数据集可以超过 40 列和 50_000 行,我该如何使用 pandas原生方法?(例如 Pivot、Transpose、Groupby)

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    用途:

    df_new=df.melt('Id',var_name='Name',value_name='Sum').groupby(['Id','Name']).Sum.sum()\
                                                                     .reset_index()
    print(df_new)
    

       Id      Name  Sum
    0  25  Filter 1    1
    1  25  Filter 2    1
    2  25  Filter 3    3
    3  30  Filter 1    1
    4  30  Filter 2    0
    5  30  Filter 3    1
    6  31  Filter 1    1
    7  31  Filter 2    1
    8  31  Filter 3    1
    

    【讨论】:

    • 感谢您的回复,善良的熊猫忍者)这也是最快的方法,在我的测试数据帧上 - 50 列和 50_000 行的计算时间不到 5 秒。
    【解决方案2】:

    stack 然后groupby

    df.set_index('Id').stack().groupby(level=[0,1]).sum().reset_index()
       Id   level_1  0
    0  25  Filter 1  1
    1  25  Filter 2  1
    2  25  Filter 3  3
    3  30  Filter 1  1
    4  30  Filter 2  0
    5  30  Filter 3  1
    6  31  Filter 1  1
    7  31  Filter 2  1
    8  31  Filter 3  1
    

    短版

    df.set_index('Id').sum(level=0).stack()#df.groupby('Id').sum().stack()
    

    【讨论】:

    • 这行得通,但在我的测试集上,它与上一个回复(melt + groupby + sum + reset_index)相比相当慢,大约需要 20 秒
    • @w00lf 你试过 df.groupby('Id').sum().stack()
    【解决方案3】:

    使用filtermelt

    df.filter(like='Filter').groupby(df.Id).sum().T.reset_index().melt(id_vars='index')
    
        index       Id  value
    0   Filter 1    25  1
    1   Filter 2    25  1
    2   Filter 3    25  3
    3   Filter 1    30  1
    4   Filter 2    30  0
    5   Filter 3    30  1
    6   Filter 1    31  1
    7   Filter 2    31  1
    8   Filter 3    31  2
    

    【讨论】:

      猜你喜欢
      • 2020-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多