【问题标题】:Un-flatten rows in dataframe取消展平数据框中的行
【发布时间】:2019-09-16 22:56:49
【问题描述】:

使用这样的数据框:

date           user    sales_blue     sales_red
2019/06/01        A            30            50
2019/06/01        B            60            70
2019/06/02        A            25            35
2019/06/02        B            42            52

我正在尝试解决以下问题:

date           user    color    sales
2019/06/01        A     blue       30
2019/06/01        A      red       50
2019/06/01        B     blue       60
2019/06/01        B      red       70
2019/06/02        A     blue       25
2019/06/02        A      red       35
2019/06/02        B     blue       42
2019/06/02        B      red       52

这通过使用循环以一种“手动”方式相当可行,但出于性能原因,我正在寻找一种更有效的解决方案,它不涉及 Python 中的循环。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    当您想要使用列名的全部 来标识行时,melt 通常是首选。但是,当您想使用列名称的较小部分(前缀为常量)时,melt 的通用、更用户友好的版本称为wide_to_long

    这不仅可以干净地处理前缀,还可以扩展以处理多个不同的前缀。

    pd.wide_to_long(
        df, stubnames='sales', i=['date', 'user'], j='color', suffix='\w+', sep='_'
    ).reset_index(-1)
    

                    color  sales
    user date
    A    2019/06/01  blue     30
         2019/06/01   red     50
    B    2019/06/01  blue     60
         2019/06/01   red     70
    A    2019/06/02  blue     25
         2019/06/02   red     35
    B    2019/06/02  blue     42
         2019/06/02   red     52
    

    将这种行为概括为熔化多个列:

    print(df)
    
             date user  sales_blue  sales_red  calls_blue  calls_red
    0  2019/06/01    A          30         50           3          4
    1  2019/06/01    B          60         70           1          2
    2  2019/06/02    A          25         35           4          6
    3  2019/06/02    B          42         52           5          7
    

    pd.wide_to_long(
      df, stubnames=['sales', 'calls'], i=['date', 'user'], j='color', suffix='\w+', sep='_'
    ).reset_index(-1)
    

                    color  sales  calls
    date       user
    2019/06/01 A     blue     30      3
               A      red     50      4
               B     blue     60      1
               B      red     70      2
    2019/06/02 A     blue     25      4
               A      red     35      6
               B     blue     42      5
               B      red     52      7
    

    【讨论】:

      【解决方案2】:

      您可以使用melt。为了从颜色中删除前缀,您可以使用 str 访问器对字符串进行切片。如果您需要指定的顺序,只需按照@anky 的建议添加.sort_values('date')

      out = df.melt(id_vars=['date', 'user'], var_name='color', value_name='sales')
      out['color'] = out.color.str[6:]
      

      print(out)
      
             date    user color  sales
      0  2019/06/01    A  blue     30
      1  2019/06/01    B  blue     60
      2  2019/06/02    A  blue     25
      3  2019/06/02    B  blue     42
      4  2019/06/01    A   red     50
      5  2019/06/01    B   red     70
      6  2019/06/02    A   red     35
      7  2019/06/02    B   red     52
      

      【讨论】:

      • 这太神奇了,不知道这个方法。为了完整起见,如果有多个要旋转的变量怎么办?例如,['sales_blue', 'sales_red', 'calls_blue', 'calls_red'] 应该变成带有蓝色/红色索引的['sales', 'calls']
      • 不确定您的意思,但问题似乎完全不同。你为什么不问一个新问题?如果你愿意,请在这里 ping 我 :) @jivan
      • 哦,这些是列@jivan 我明白你的意思。好吧,您仍然可以使用melt,需要一些额外的工作是对颜色列进行切片以获得颜色
      猜你喜欢
      • 2017-08-09
      • 2014-12-04
      • 1970-01-01
      • 2012-03-17
      • 1970-01-01
      • 2022-01-22
      • 2015-03-14
      • 1970-01-01
      • 2019-03-08
      相关资源
      最近更新 更多