【问题标题】:Pandas reshape a multicolumn dataframe long to wide with conditional checkPandas 通过条件检查将多列数据框从长到宽重塑
【发布时间】:2019-08-31 22:30:04
【问题描述】:

我有一个pandas 数据框如下:

id     group    type    action    cost
101    A        1                 10
101    A        1       repair    3
102    B        1                 5
102    B        1       repair    7
102    B        1       grease    2
102    B        1       inflate   1
103    A        2                 12
104    B        2                 9

我需要把它从长改成宽,但要根据action列的值,如下:

id     group    type    action_std    action_extra
101    A        1       10            3
102    B        1       5             10
103    A        2       12            0
104    B        2       9             0

换句话说,对于action 字段为空的行,cost 值应放在action_std 列下,而对于action 字段非空的行,cost 值应为在action_extra 列下汇总。

我尝试了groupby/agg/pivot 的几种组合,但我找不到任何完全有效的解决方案...

【问题讨论】:

    标签: python pandas reshape


    【解决方案1】:

    我建议您简单地将cost 列拆分为costcost_extra 列。类似于以下内容:

    import numpy as np
    
    result = df.assign(
        cost_extra=lambda df: np.where(
            df['action'].notnull(), df['cost'], np.nan
        )
    ).assign(
        cost=lambda df: np.where(
            df['action'].isnull(), df['cost'], np.nan
        )
    ).groupby(
        ["id", "group", "type"]
    )["cost", "cost_extra"].agg(
        "sum"
    )
    

    result 看起来像:

                    cost  cost_extra
    id  group type                  
    101 A     1     10.0         3.0
    102 B     1      5.0        10.0
    103 A     2     12.0         0.0
    104 B     2      9.0         0.0
    

    【讨论】:

    • 您可以assign 一次使用逗号分隔两列。
    【解决方案2】:

    检查groupbyunstack

    df.cost.groupby([df.id,df.group,df.type,df.action.eq('')]).sum().unstack(fill_value=0)
    action          False  True 
    id  group type              
    101 A     1         3     10
    102 B     1        10      5
    103 A     2         0     12
    104 B     2         0      9
    

    【讨论】:

      【解决方案3】:

      感谢您的提示,这是我最终最喜欢的解决方案(也因为它的简单性):

      df["action_std"] = df["cost"].where(df["action"] == "")
      df["action_extra"] = df["cost"].where(df["action"] != "")
      df = df.groupby(["id", "group", "type"])["action_std", "action_extra"].sum().reset_index()
      

      【讨论】:

        猜你喜欢
        • 2018-05-08
        • 1970-01-01
        • 1970-01-01
        • 2017-05-05
        • 2017-08-08
        • 2019-11-22
        • 2014-08-19
        相关资源
        最近更新 更多