【问题标题】:How do I convert multiple columns to individual rows/values in pandas?如何在熊猫中将多列转换为单独的行/值?
【发布时间】:2020-05-07 19:36:31
【问题描述】:

我确定这个问题已经得到解答,但不幸的是我不知道如何调用这个操作,所以我的搜索失败了。它几乎就像一个反向数据透视表。

假设我有以下工资单数据:

data = [
    {'employee': 1, 'date': '2020-01-04', 'reg': 8, 'ot': 0, 'dt': 0},
    {'employee': 1, 'date': '2020-01-05', 'reg': 4, 'ot': 4, 'dt': 0},
    {'employee': 1, 'date': '2020-01-06', 'reg': 0, 'ot': 0, 'dt': 4},
    {'employee': 2, 'date': '2020-01-04', 'reg': 6, 'ot': 2, 'dt': 0},
    {'employee': 2, 'date': '2020-01-05', 'reg': 3, 'ot': 5, 'dt': 0},
    {'employee': 2, 'date': '2020-01-06', 'reg': 0, 'ot': 4, 'dt': 0},
]

data_df = pd.DataFrame(data)

我需要做的是将每个员工/日期的每个费率(“reg”、“ot”和“dt”)分解成自己的行,其中有一列是费率标签,一列是小时数,保留其他非基于速率的列。此外,我不希望值为零的任何费率有一行。对于上面的数据,我希望得到:

result = [
    {'employee': 1, 'date': '2020-01-04', 'rate': 'reg', 'hours': 8},
    {'employee': 1, 'date': '2020-01-05', 'rate': 'reg', 'hours': 4},
    {'employee': 1, 'date': '2020-01-05', 'rate': 'ot', 'hours': 4},
    {'employee': 1, 'date': '2020-01-06', 'rate': 'dt', 'hours': 4},
    {'employee': 2, 'date': '2020-01-04', 'rate': 'reg', 'hours': 6},
    {'employee': 2, 'date': '2020-01-04', 'rate': 'ot', 'hours': 2},
    {'employee': 2, 'date': '2020-01-05', 'rate': 'reg', 'hours': 3},
    {'employee': 2, 'date': '2020-01-05', 'rate': 'ot', 'hours': 5},
    {'employee': 2, 'date': '2020-01-06', 'rate': 'ot', 'hours': 4},
]

result_df = pd.DataFrame(result)

任何关于如何实现这一点的想法将不胜感激!

【问题讨论】:

    标签: python pandas dataframe reshape


    【解决方案1】:

    尝试使用melt

    (data_df.melt(['employee','date'], 
                 var_name='rate', 
                 value_name='hours')
            .query('hours != 0'))
    

    输出:

        employee        date rate  hours
    0          1  2020-01-04  reg      8
    1          1  2020-01-05  reg      4
    3          2  2020-01-04  reg      6
    4          2  2020-01-05  reg      3
    7          1  2020-01-05   ot      4
    9          2  2020-01-04   ot      2
    10         2  2020-01-05   ot      5
    11         2  2020-01-06   ot      4
    14         1  2020-01-06   dt      4
    

    【讨论】:

    • Melt 在重命名方面做得更好。但是我真的很鄙视排序优先级是[col,row]。 +1。
    【解决方案2】:

    这应该可以解决问题:

    data_df=data_df.set_index(["employee", "date"]).stack().reset_index().rename(columns={"level_2": "rate", 0: "hours"})
    

    输出:

        employee        date rate  hours
    0          1  2020-01-04  reg      8
    1          1  2020-01-04   ot      0
    2          1  2020-01-04   dt      0
    3          1  2020-01-05  reg      4
    4          1  2020-01-05   ot      4
    5          1  2020-01-05   dt      0
    6          1  2020-01-06  reg      0
    7          1  2020-01-06   ot      0
    8          1  2020-01-06   dt      4
    9          2  2020-01-04  reg      6
    10         2  2020-01-04   ot      2
    11         2  2020-01-04   dt      0
    12         2  2020-01-05  reg      3
    13         2  2020-01-05   ot      5
    14         2  2020-01-05   dt      0
    15         2  2020-01-06  reg      0
    16         2  2020-01-06   ot      4
    17         2  2020-01-06   dt      0
    

    【讨论】:

      猜你喜欢
      • 2020-03-23
      • 2021-01-06
      • 2021-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-05
      • 1970-01-01
      相关资源
      最近更新 更多