【问题标题】:Is there a way to use the melt function in Python for multiple columns?有没有办法将 Python 中的 melt 函数用于多列?
【发布时间】:2016-05-24 19:40:31
【问题描述】:

我有一个交叉表格式的表格,示例如下:

State   Item #  x1  x2  x3  y1  y2  y3  z1  z2  z3
CA      1       6   4   3   7   5   3       11      5       1
CA      2       7   3   1   15  10  5       4       2       1
FL      3       3   2   1   5   3   2       13      7       2
FL      4       9   4   2   16  14  12      14      5       4

我正在尝试使用 melt 功能将数据按以下格式放置:

State   Item #  x   xvalue  y   yvalue  z   zvalue
CA      1       x1    6     y1    7     z1    11
CA      1       x2    4     y2    5     z2    5
CA      1       x3    3     y3    3     z3    1
CA      2       x1    7     y1    15    z1    4
CA      2       x2    3     y2    10    z2    2
CA      2       x3    1     y3    5     z3    1    

我知道如何使用 melt 函数仅对其中一个值执行此操作,例如 x。但我也不知道如何处理 y 和 z 。请参阅下面的代码以仅针对 x 执行此操作。有没有办法我可以调整它来为 y 和 z 做呢?或者我应该尝试为 x、y 和 z 设置单独的熔化函数,然后以某种方式将它们组合起来?

df_m = pd.melt(df, id_vars=['State', 'Item #'],
           value_vars=['x1','x2','x3'],
           var_name='x', value_name='xvalue')

【问题讨论】:

  • 我认为您可能需要进行多次熔化。

标签: python pandas melt


【解决方案1】:

我不这么认为,但您可以使用两行解决方案:

values = [['x1','x2','x3'], ['y1', 'y2', 'y3'], ['z1', 'z2', 'z3']]

df_m = pd.concat([pd.melt(df, id_vars=['State', 'Item_#'], value_vars=val, var_name='var', value_name='value') for val in values])

pd.concat 函数是一种强大(即快速)垂直堆叠 DataFrame 的方法。

【讨论】:

    【解决方案2】:

    这是一个不使用 melt 但适用于任意数量的 xyz '组'的版本。

    import pandas as pd
    from io import StringIO
    
    df = pd.read_csv(StringIO('''
        State   ItemN  x1  x2  x3  y1  y2  y3  z1  z2  z3
    CA      1       6   4   3   7   5   3       11      5       1
    CA      2       7   3   1   15  10  5       4       2       1
    FL      3       3   2   1   5   3   2       13      7       2
    FL      4       9   4   2   16  14  12      14      5       4'''),
    sep=r' +')
    
    # prepare index
    df = df.set_index(list(df.columns[:2]))
    df.columns = pd.MultiIndex.from_tuples([(c[0], c) for c in df.columns])
    
    #              x         y           z      
    #             x1 x2 x3  y1  y2  y3  z1 z2 z3
    # State ItemN                               
    # CA    1      6  4  3   7   5   3  11  5  1
    #       2      7  3  1  15  10   5   4  2  1
    # FL    3      3  2  1   5   3   2  13  7  2
    #       4      9  4  2  16  14  12  14  5  4
    
    
    # stack and concat each 'group'
    df2 = pd.concat((
        df[c].stack().reset_index(-1)
        for c in df.columns.levels[0]),
        axis=1)
    
    # rename the columns
    new_cols = [None for _ in range(df2.shape[1])]
    new_cols[::2]  = [c for c in df.columns.levels[0]]
    new_cols[1::2] = [c + 'value' for c in df.columns.levels[0]]
    
    df2.columns = new_cols
    
    #               x  xvalue   y  yvalue   z  zvalue
    # State ItemN                                    
    # CA    1      x1       6  y1       7  z1      11
    #       1      x2       4  y2       5  z2       5
    #       1      x3       3  y3       3  z3       1
    #       2      x1       7  y1      15  z1       4
    #       2      x2       3  y2      10  z2       2
    #       2      x3       1  y3       5  z3       1
    # FL    3      x1       3  y1       5  z1      13
    #       3      x2       2  y2       3  z2       7
    #       3      x3       1  y3       2  z3       2
    #       4      x1       9  y1      16  z1      14
    #       4      x2       4  y2      14  z2       5
    #       4      x3       2  y3      12  z3       4
    

    【讨论】:

      【解决方案3】:

      pd.wide_to_long 呢?

      # Make dataframe
      df = pd.DataFrame({'State' : ['CA']*2 + ['FL']*2,
                         'Item' : [1, 2, 3, 4],
                         'x1' : [6, 7, 3, 9],
                         'x2' : [4, 3, 2, 4],
                         'x3' : [3, 1, 1, 2],
                         'y1' : [7, 15, 5, 16],
                         'y2' : [5, 10, 3, 14],
                         'y3' : [3, 5, 2, 12],
                         'z1' : [11, 4, 13, 14],
                         'z2' : [5, 2, 7, 5],
                         'z3' : [1, 1, 2, 4]})
      
      # Make final dataframe using pd.wide_to_long
      final = pd.wide_to_long(df,
                              stubnames = ['x', 'y', 'z'],
                              i = ['State',
                                   'Item'],
                              j = 'number').reset_index()
      
      # Show final dataframe
      final
      

      我知道返回的数据帧与您请求的数据帧不完全一样,但它仍然可以工作。事实上,它现在将您的 x、y、z、xvalue、yvalue 和 zvalue 列组合成 x、y、z 和一个“数字”列,用于引用第一个、第二个和第三个值。

      【讨论】:

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