【问题标题】:How do I one-hot encode pandas dataframe for whole columns, not for each column?如何对整列而不是每列的熊猫数据框进行一次热编码?
【发布时间】:2023-03-31 10:37:02
【问题描述】:

我想对整个列而不是每一列的 pandas 数据帧进行一次热编码。

如果有如下数据框:

df = pd.DataFrame({'A': ['A1', 'A1', 'A1', 'A1', 'A4', 'A5'], 'B': ['A2', 'A2', 'A2', 'A3', np.nan, 'A6], 'C': ['A4', 'A3', 'A3', 'A5', np.nan, np.nan]})
df =
        A    B   C
    0  A1   A2  A4
    1  A1   A2  A3
    2  A1   A2  A3
    3  A1   A3  A5
    4  A4   NaN NaN
    5  A5   A6  NaN

我想像下面这样编码:

    df =
            A1    A2   A3   A4   A5   A6
        0    1     1    0    1    0    0
        1    1     1    1    0    0    0
        2    1     1    1    0    0    0
        3    1     0    1    0    1    0
        4    0     0    0    1    0    0
        5    0     0    0    0    1    1

但是,如果我编写如下代码,结果如下:

df = pd.get_dummies(df, sparse=True)
df = 
   A_A1  A_A4  A_A5  B_A2  B_A3  B_A6  C_A3  C_A4  C_A5
0     1     0     0     1     0     0     0     1     0
1     1     0     0     1     0     0     1     0     0
2     1     0     0     1     0     0     1     0     0
3     1     0     0     0     1     0     0     0     1
4     0     1     0     0     0     0     0     0     0
5     0     0     1     0     0     1     0     0     0

如何对整列进行一次热编码? 如果我使用前缀 = '',它还会生成 _A1 _A4 _A5 _A2 _A3 _A6 _A3 _A4 _A5 等列。 (我希望使用 pandas 或 numpy 库来编写代码,而不是 for-loop naive 代码,因为我的数据非常庞大;16000000 行,因此迭代 for-loop naive 代码需要很长的计算时间。

【问题讨论】:

    标签: pandas one-hot-encoding


    【解决方案1】:

    你的情况

    df.stack().str.get_dummies().sum(level=0)
    Out[116]: 
       A1  A2  A3  A4  A5  A6
    0   1   1   0   1   0   0
    1   1   1   1   0   0   0
    2   1   1   1   0   0   0
    3   1   0   1   0   1   0
    4   0   0   0   1   0   0
    5   0   0   0   0   1   1
    

    或者用prefix修复你的pd.get_dummies

    pd.get_dummies(df, prefix='',prefix_sep='').sum(level=0,axis=1)
    Out[118]: 
       A1  A4  A5  A2  A3  A6
    0   1   1   0   1   0   0
    1   1   0   0   1   1   0
    2   1   0   0   1   1   0
    3   1   0   1   0   1   0
    4   0   1   0   0   0   0
    5   0   0   1   0   0   1
    

    【讨论】:

    • 很好,也想知道哪个更快。 :) (IYO)
    • @anky_91 对于更大的数据集,我认为pd.get_dummies 更快
    【解决方案2】:

    更快

    # Pandas 0.24 or greater use `.to_numpy()` instead of `.values`
    v = df.values
    n, m = v.shape
    j, cols = pd.factorize(v.ravel())  # -1 when `np.nan`
    
    # Used to grab only non-null values
    mask = j >= 0
    i = np.arange(n).repeat(m)[mask]
    j = j[mask]
    
    out = np.zeros((n, len(cols)), dtype=int)
    # Useful when not one-hot.  Otherwise use `out[i, j] = 1`
    np.add.at(out, (i, j), 1)
    
    pd.DataFrame(out, df.index, cols)
    
       A1  A2  A4  A3  A5  A6
    0   1   1   1   0   0   0
    1   1   1   0   1   0   0
    2   1   1   0   1   0   0
    3   1   0   0   1   1   0
    4   0   0   1   0   0   0
    5   0   0   0   0   1   1
    

    不是更快

    这是为了表明您可以加入行值然后使用str.get_dummies

    df.stack().groupby(level=0).apply('|'.join).str.get_dummies()
    
       A1  A2  A3  A4  A5  A6
    0   1   1   0   1   0   0
    1   1   1   1   0   0   0
    2   1   1   1   0   0   0
    3   1   0   1   0   1   0
    4   0   0   0   1   0   0
    5   0   0   0   0   1   1
    

    sklearn

    from sklearn.preprocessing import MultiLabelBinarizer as MLB
    
    mlb = MLB()
    out = mlb.fit_transform([[*filter(pd.notna, x)] for x in zip(*map(df.get, df))])
    
    pd.DataFrame(out, df.index, mlb.classes_)
    
       A1  A2  A3  A4  A5  A6
    0   1   1   0   1   0   0
    1   1   1   1   0   0   0
    2   1   1   1   0   0   0
    3   1   0   1   0   1   0
    4   0   0   0   1   0   0
    5   0   0   0   0   1   1
    

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 2021-11-16
      • 1970-01-01
      • 2017-05-02
      • 2019-02-10
      • 2017-09-05
      • 2016-10-13
      相关资源
      最近更新 更多