【问题标题】:How do I perform One Hot Encoding on lists in a pandas column?如何对 pandas 列中的列表执行 One Hot Encoding?
【发布时间】:2019-10-11 10:06:04
【问题描述】:

假设我有一个数据框,其中一列是一个列表(值和长度未知),例如:

df = pd.DataFrame(
 {'messageLabels': [['Good', 'Other', 'Bad'],['Bad','Terrible']]}
)

我遇到了这个解决方案,但这不是我想要的。 How best to extract a Pandas column containing lists or tuples into multiple columns

理论上得到的df看起来像

messageLabels             | Good| Other| Bad| Terrible
--------------------------------------------------------
['Good', 'Other', 'Bad']  | True| True |True| False
--------------------------------------------------------
['Bad','Terrible']        |False|False |True| True

见上

【问题讨论】:

    标签: python pandas list


    【解决方案1】:

    我会使用get_dummiessum(或max,它们都可以)来做到这一点:

    tmp = pd.DataFrame(df['messageLabels'].tolist())
    pd.get_dummies(tmp, prefix='', prefix_sep='').max(level=0, axis=1).astype(bool)
    
        Bad   Good  Other  Terrible
    0  True   True   True     False
    1  True  False  False      True
    

    您可以将其与df 结合使用join

    df.join(pd.get_dummies(tmp, prefix='', prefix_sep='')
              .max(level=0, axis=1)
              .astype(bool))
    
            messageLabels   Bad   Good  Other  Terrible
    0  [Good, Other, Bad]  True   True   True     False
    1     [Bad, Terrible]  True  False  False      True
    

    你也可以stackpivot_table:

    (pd.DataFrame(df['messageLabels'].tolist())
       .stack()
       .reset_index()
       .pivot_table(index='level_0', columns=0, aggfunc='size', fill_value=0)
       .astype(bool))
    
    0         Bad   Good  Other  Terrible
    level_0                              
    0        True   True   True     False
    1        True  False  False      True
    

    【讨论】:

      【解决方案2】:

      简洁

      df.join(df.messageLabels.str.join('|').str.get_dummies().astype(bool))
      
              messageLabels   Bad   Good  Other  Terrible
      0  [Good, Other, Bad]  True   True   True     False
      1     [Bad, Terrible]  True  False  False      True
      

      sklearn

      from sklearn.preprocessing import MultiLabelBinarizer
      
      mlb = MultiLabelBinarizer()
      dum = mlb.fit_transform(df.messageLabels)
      
      df.join(pd.DataFrame(dum.astype(bool), df.index, mlb.classes_))
      
              messageLabels   Bad   Good  Other  Terrible
      0  [Good, Other, Bad]  True   True   True     False
      1     [Bad, Terrible]  True  False  False      True
      

      过头了

      n = len(df)
      i = np.arange(n)
      l = [*map(len, df.messageLabels)]
      j, u = pd.factorize(np.concatenate(df.messageLabels))
      
      o = np.zeros((n, len(u)), bool)
      o[i.repeat(l), j] = True
      
      df.join(pd.DataFrame(o, df.index, u))
      
              messageLabels   Good  Other   Bad  Terrible
      0  [Good, Other, Bad]   True   True  True     False
      1     [Bad, Terrible]  False  False  True      True
      

      胡闹

      并受到Andy的启发

      df.join(pd.DataFrame([dict.fromkeys(x, True) for x in df.messageLabels]).fillna(False))
      
              messageLabels   Bad   Good  Other  Terrible
      0  [Good, Other, Bad]  True   True   True     False
      1     [Bad, Terrible]  True  False  False      True
      

      【讨论】:

        【解决方案3】:

        另一种方法是使用 apply 和 Series 构造函数:

        In [11]: pd.get_dummies(df.messageLabels.apply(lambda x: pd.Series(1, x)) == 1)
        Out[11]:
            Good  Other   Bad  Terrible
        0   True   True  True     False
        1  False  False  True      True
        

        在哪里

        In [12]: df.messageLabels.apply(lambda x: pd.Series(1, x))
        Out[12]:
           Good  Other  Bad  Terrible
        0   1.0    1.0  1.0       NaN
        1   NaN    NaN  1.0       1.0
        

        要获得所需的输出:

        In [21]: res = pd.get_dummies(df.messageLabels.apply(lambda x: pd.Series(1, x)) == 1)
        
        In [22]: df[res.columns] = res
        
        In [23]: df
        Out[23]:
                messageLabels   Good  Other   Bad  Terrible
        0  [Good, Other, Bad]   True   True  True     False
        1     [Bad, Terrible]  False  False  True      True
        

        【讨论】:

        • 嘿!并解释这个pd.get_dummies(df.messageLabels.apply(lambda x: pd.Series(True, x)))
        • @piRSquared 所以你可以在没有 get_dummies 的情况下使用df.messageLabels.apply(lambda x: pd.Series(True, x)).fillna(False)
        • 我在我的帖子中添加了一个版本。 dict.fromkeys
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-09
        • 1970-01-01
        • 2021-04-12
        • 2019-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多