【问题标题】:Melting pandas data frame with multiple variable names and multiple value names熔化具有多个变量名称和多个值名称的熊猫数据框
【发布时间】:2018-01-21 13:51:03
【问题描述】:

如何使用多个变量名称和值融合 pandas 数据框?我有以下数据框,它在 for 循环中改变了它的形状。在其中一次 for 循环迭代中,它看起来像这样:

ID  Cat    Class_A   Class_B     Prob_A     Prob_B
1   Veg      1        2          0.9         0.1
2   Veg      1        2          0.8         0.2
3   Meat     1        2          0.6         0.4
4   Meat     1        2          0.3         0.7
5   Veg      1        2          0.2         0.8

我需要把它融化成这样:

ID  Cat    Class     Prob    
1   Veg      1       0.9       
1   Veg      2       0.1
2   Veg      1       0.8        
2   Veg      2       0.2
3   Meat     1       0.6         
3   Meat     2       0.4
4   Meat     1       0.3         
4   Meat     2       0.7
5   Veg      1       0.2         
5   Veg      2       0.8

在 for 循环期间,数据框将包含不同数量的类及其概率。这就是为什么我正在寻找一种适用于我所有 for 循环迭代的通用方法。我看到了 questionthis 但它们没有帮助!

【问题讨论】:

    标签: python pandas melt


    【解决方案1】:

    您需要lreshape by dict 来指定类别:

    d = {'Class':['Class_A', 'Class_B'], 'Prob':['Prob_A','Prob_B']}
    df = pd.lreshape(df,d)
    print (df)
        Cat  ID  Class  Prob
    0   Veg   1      1   0.9
    1   Veg   2      1   0.8
    2  Meat   3      1   0.6
    3  Meat   4      1   0.3
    4   Veg   5      1   0.2
    5   Veg   1      2   0.1
    6   Veg   2      2   0.2
    7  Meat   3      2   0.4
    8  Meat   4      2   0.7
    9   Veg   5      2   0.8
    

    更动态的解决方案:

    Class = [col for col in df.columns if col.startswith('Class')]
    Prob = [col for col in df.columns if col.startswith('Prob')]
    df = pd.lreshape(df, {'Class':Class, 'Prob':Prob})
    print (df)
        Cat  ID  Class  Prob
    0   Veg   1      1   0.9
    1   Veg   2      1   0.8
    2  Meat   3      1   0.6
    3  Meat   4      1   0.3
    4   Veg   5      1   0.2
    5   Veg   1      2   0.1
    6   Veg   2      2   0.2
    7  Meat   3      2   0.4
    8  Meat   4      2   0.7
    9   Veg   5      2   0.8
    

    编辑:

    lreshape 现在没有记录,但将来可能会被删除 (with pd.wide_to_long too)。

    可能的解决方案是将所有 3 个功能合并为一个 - 可能是 melt,但现在尚未实施。也许在一些新版本的熊猫中。然后我的答案会更新。

    【讨论】:

    • @jezrael:如果我需要在 Class 下显示类的名称(''Class_A'、'Class_B')而不是它们的代码('1'、'2'),该怎么办?
    • 我认为最简单的是df['Class_A'] = 'Class_A'df['Class_B'] = 'Class_B' - 用标量列替换值,然后使用lreshape
    • @jezrael 我认为未记录的函数不好用,因为您必须直接链接到源代码。有人说要删除lreshape
    • @Ted Petrou - 感谢您的评论。是的,有时将来功能可以删除或不删除是可能的,这两个功能都很少使用。但我认为这不是投反对票的理由:(
    • 我认为这个答案真的很糟糕,这就是我投反对票的原因。你还有 10 票。在我看来,您几乎不应该使用未记录的功能,尤其是那些具有同等和优越对应物的功能,例如pd.wide_to_long。现在人们会提出这个问题,并认为这是同时熔化两列的正确方法。任何人都不应该在生产中使用它。
    【解决方案2】:

    或者你可以使用str.containpd.concat试试这个

    DF1=df2.loc[:,df2.columns.str.contains('_A|Cat|ID')]
    name=['ID','Cat','Class','Prob']
    DF1.columns=name
    DF2=df2.loc[:,df2.columns.str.contains('_B|Cat|ID')]
    DF2.columns=name
    pd.concat([DF1,DF2],axis=0)
    
    Out[354]: 
       ID   Cat  Class  Prob
    0   1   Veg      1   0.9
    1   2   Veg      1   0.8
    2   3  Meat      1   0.6
    3   4  Meat      1   0.3
    4   5   Veg      1   0.2
    0   1   Veg      2   0.1
    1   2   Veg      2   0.2
    2   3  Meat      2   0.4
    3   4  Meat      2   0.7
    4   5   Veg      2   0.8
    

    【讨论】:

      【解决方案3】:

      投票最多的答案使用未记录的lreshape,因为它与记录在案并可直接在此处使用的pd.wide_to_long 相似,因此在某些时候可能会被弃用。默认情况下,suffix 仅匹配数字。您必须更改它以匹配字符(这里我只使用了任何字符)。

      pd.wide_to_long(df, stubnames=['Class', 'Prob'], i=['ID', 'Cat'], j='DROPME', suffix='.')\
        .reset_index()\
        .drop('DROPME', axis=1)
      
         ID   Cat  Class  Prob
      0   1   Veg      1   0.9
      1   1   Veg      2   0.1
      2   2   Veg      1   0.8
      3   2   Veg      2   0.2
      4   3  Meat      1   0.6
      5   3  Meat      2   0.4
      6   4  Meat      1   0.3
      7   4  Meat      2   0.7
      8   5   Veg      1   0.2
      9   5   Veg      2   0.8
      

      【讨论】:

        【解决方案4】:

        你也可以使用pd.melt

        # Make DataFrame
        df = pd.DataFrame({'ID' :  [i for i in range(1,6)],
                           'Cat' : ['Veg']*2 + ['Meat']*2 + ['Veg'],
                           'Class_A' : [1]*5,
                           'Class_B' : [2]*5,
                           'Prob_A' : [0.9, 0.8, 0.6, 0.3, 0.2],
                           'Prob_B' : [0.1, 0.2, 0.4, 0.7, 0.8]})
        
        # Make class dataframe and prob dataframe
        df_class = df.loc[:, ['ID', 'Cat', 'Class_A', 'Class_B']]
        df_prob = df.loc[:, ['ID', 'Cat', 'Prob_A', 'Prob_B']]
        
        # Melt class dataframe and prob dataframe
        df_class = df_class.melt(id_vars = ['ID',
                                            'Cat'],
                                 value_vars = ['Class_A',
                                               'Class_B'],
                                 value_name = 'Class')
        df_prob = df_prob.melt(id_vars = ['ID',
                                          'Cat'],
                               value_vars = ['Prob_A',
                                             'Prob_B'],
                               value_name = 'Prob')
        
        # Clean variable column so only 'A','B' is left in both dataframes
        df_class.loc[:, 'variable'] = df_class.loc[:, 'variable'].str.partition('_')[2]
        df_prob.loc[:, 'variable'] = df_prob.loc[:, 'variable'].str.partition('_')[2]
        
        # Merge class dataframe with prob dataframe on 'ID', 'Cat', and 'variable';
        # drop 'variable'; sort values by 'ID', 'Cat'
        final = df_class.merge(df_prob,
                               how = 'inner',
                               on = ['ID',
                                     'Cat',
                                     'variable']).drop('variable', axis = 1).sort_values(by = ['ID',
                                                                                               'Cat'])
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-02-20
          • 2019-09-30
          • 1970-01-01
          • 2017-05-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多