【问题标题】:Switch columns and row on a dataframe在数据框上切换列和行
【发布时间】:2023-01-11 05:40:39
【问题描述】:

我有一个熊猫数据框,我需要“切换”行和列。 (转置?枢轴?融化?不知道它是怎么称呼的):

假设我有 2 个引用,每个引用有 4 个步骤,每个步骤有 3 个变量

df = pd.DataFrame({'ref': ['ref1', 'ref1', 'ref1', 'ref1', 'ref2', 'ref2', 'ref2', 'ref2'],
                   'step': [1, 2, 3, 4, 1, 2, 3, 4],
                   'var_1': [5, 7, 7, 9, 12, 9, 87, 90],
                   'var_2': [11, 8, 10, 6, 6, 9, 12, 9],
                   "var_3": [11, 8, 10, 6, 6, 9, 12, 9]})



我想将此 df 转换为这种形式:

df = pd.DataFrame({'ref': ['ref1', 'ref2'],
>                    'step 1 - var_1': [5, 12],
>                    'step 1 - var_2': [11, 6],
>                    'step 1 - var_3': [11, 6],
>                    'step 2 - var_1': [7, 12],
>                    'step 2 - var_2': [8, 9],
>                    'step 2 - var_3': [8, 9]})




先感谢您, 最好

编辑:格式和图像

【问题讨论】:

  • 输入与输出如何对应?
  • 从输出列中,它声音就像您可能想要 df.explode('step') 然后 rename(),但行值与此不对应。

标签: python pandas pivot transpose


【解决方案1】:

在一行代码中使用新的“walrus”运算符试试这个:

(df_new := df.set_index(['ref', 'step']).unstack().sort_index(level=1, axis=1))
    .set_axis([f'step {j} - {i}' for i, j in df_new.columns], axis=1)

输出:

      step 1 - var_1  step 1 - var_2  step 1 - var_3  step 2 - var_1  step 2 - var_2  step 2 - var_3  step 3 - var_1  step 3 - var_2  step 3 - var_3  step 4 - var_1  step 4 - var_2  step 4 - var_3
ref                                                                                                                                                                                                 
ref1               5              11              11               7               8               8               7              10              10               9               6               6
ref2              12               6               6               9               9               9              87              12              12              90               9               9

细节:

  • set_index 包含列 ref 和 step
  • unstack步移入列
  • 使用sort_index 为您排序列
  • 使用set_axis 和列表扁平化多索引数据框列标题 理解 f 字符串格式

与上述订单相同的替代方式,

df_out = df.pivot(index='ref', columns='step').sort_index(level=1, axis=1)
df_out.columns = [f'step {j} - {i}' for i, j in df_out.columns]

【讨论】:

    【解决方案2】:

    一种选择是使用来自 pyjnanitorpivot_wider,通过 names_glue 参数抽象列重命名:

    # pip insall pyjanitor
    import pandas as pd
    import janitor
    (df
    .pivot_wider(
        index='ref', 
        names_from='step',  
        values_from = ['var_1', 'var_2', 'var_3'],
        names_glue = "step {step} - {_value}")
    .sort_index(axis=1)
    ) 
        ref  step 1 - var_1  step 1 - var_2  step 1 - var_3  ...  step 3 - var_3  step 4 - var_1  step 4 - var_2  step 4 - var_3
    0  ref1               5              11              11  ...              10               9               6               6
    1  ref2              12               6               6  ...              12              90               9               9
    
    [2 rows x 13 columns]
    

    names_glue 允许 values_fromnames_from 参数的组合 - 在上面的代码中 {step} 是 names_from 参数,而 {_value}values_from 的占位符

    如果我们严格遵守您的输出,则应在 step 列上执行过滤器,仅针对小于 3 的值:

    (df
    .loc[df.step < 3]
    .pivot_wider(
        index='ref', 
        names_from='step', 
        names_glue = "step {step} - {_value}")
    .sort_index(axis=1)
    ) 
        ref  step 1 - var_1  step 1 - var_2  step 1 - var_3  step 2 - var_1  step 2 - var_2  step 2 - var_3
    0  ref1               5              11              11               7               8               8
    1  ref2              12               6               6               9               9               9
    

    【讨论】:

      【解决方案3】:

      利用:

      df[df.step<3].set_index(['ref','step']).unstack()
      

      输出:

           var_1    var_2    var_3   
      step     1  2     1  2     1  2
      ref                            
      ref1     5  7    11  8    11  8
      ref2    12  9     6  9     6  9
      

      【讨论】:

      • 如果您提供更简单和正确的方法,看起来您仍然会被否决。
      • 这是一个好方法,但需要更改列标题以匹配 OP 的请求。
      【解决方案4】:

      诀窍是使用df.pivot。您可以选择index='ref'columns='step'

      new = df.pivot(index='ref', columns='step')
      

      生成的表具有 ref 的多索引和多列。多列有 step 和 var 信息,所以我们可以用它来制作新的列标题。最后,我们可以重置索引:

      new.columns = [f'step {x[1]} - {x[0]}' for x in new.columns]
      new = new.reset_index()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-29
        • 1970-01-01
        • 1970-01-01
        • 2022-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多