【问题标题】:Label encoding multiple columns with the same category标签编码具有相同类别的多个列
【发布时间】:2018-07-14 18:25:17
【问题描述】:

考虑以下数据框:

import pandas as pd
from sklearn.preprocessing import LabelEncoder

df = pd.DataFrame(data=[["France", "Italy", "Belgium"], ["Italy", "France", "Belgium"]], columns=["a", "b", "c"])
df = df.apply(LabelEncoder().fit_transform)
print(df)

目前输出:

   a  b  c
0  0  1  0
1  1  0  0

我的目标是通过传入我想要共享分类值的列来使其输出类似的内容:

   a  b  c
0  0  1  2
1  1  0  2

【问题讨论】:

    标签: python pandas scikit-learn


    【解决方案1】:

    您可以使用pd.factorize 来做到这一点。

    df = df.stack()
    df[:] = pd.factorize(df)[0]
    df.unstack()
    
       a  b  c
    0  0  1  2
    1  1  0  2
    

    如果您只想encode 数据框中的某些列,那么:

    temp = df[['a', 'b']].stack()
    temp[:] = temp.factorize()[0]
    df[['a', 'b']] = temp.unstack()
    
       a  b        c
    0  0  1  Belgium
    1  1  0  Belgium
    

    【讨论】:

    • 对我不起作用。它给了我 0 a 0 b 1 c 2 1 a 3 b 0 c 2
    • @Martin:检查您的原始df 中是否有拼写错误——尤其是第二行的“Italy”。
    • 你是对的,我的错。我忘了我曾尝试在第一排将意大利换成瑞典。我对这个问题的意思是它应该适用于所有行,第一个答案中的第二种方法确实如此,尽管我现在可以看到我的定义中的歧义。
    【解决方案2】:

    这是使用分类数据的替代解决方案。类似于@unutbu,但保留了分解的顺序。换句话说,找到的第一个值的代码为 0。

    df = pd.DataFrame(data=[["France", "Italy", "Belgium"],
                            ["Italy", "France", "Belgium"]],
                      columns=["a", "b", "c"])
    
    # get unique values in order
    vals = df.T.stack().unique()
    
    # convert to categories and then extract codes
    for col in df:
        df[col] = pd.Categorical(df[col], categories=vals)
        df[col] = df[col].cat.codes
    
    print(df)
    
       a  b  c
    0  0  1  2
    1  1  0  2
    

    【讨论】:

    • pd.factorize() 做同样的事情吗?
    • @Dark,是的。您选择此解决方案而不是因式分解的唯一原因是您打算使用分类特征(例如验证),而代码视图只是一种替代表示。
    【解决方案3】:

    如果编码顺序无关紧要,你可以这样做:

    df_new = (         
        pd.DataFrame(columns=df.columns,
                     data=LabelEncoder()
                     .fit_transform(df.values.flatten()).reshape(df.shape))
    )
    
    df_new
    Out[27]: 
       a  b  c
    0  1  2  0
    1  2  1  0
    

    【讨论】:

    • 有没有办法在这里获取映射?并且:我实际上认为你解决了一个问题here
    【解决方案4】:

    每行通过axis=1 调用LabelEncoder().fit_transform 一次。 (默认情况下,df.apply(func) 每列调用一次func

    import pandas as pd
    from sklearn.preprocessing import LabelEncoder
    
    df = pd.DataFrame(data=[["France", "Italy", "Belgium"], 
                            ["Italy", "France", "Belgium"]], columns=["a", "b", "c"])
    
    encoder = LabelEncoder()
    
    df = df.apply(encoder.fit_transform, axis=1)
    print(df)
    

    产量

       a  b  c
    0  1  2  0
    1  2  1  0
    

    或者,您可以使用 category dtype 的数据并使用类别代码作为标签:

    import pandas as pd
    
    df = pd.DataFrame(data=[["France", "Italy", "Belgium"], 
                            ["Italy", "France", "Belgium"]], columns=["a", "b", "c"])
    
    stacked = df.stack().astype('category')
    result = stacked.cat.codes.unstack()
    print(result)
    

    也产生

       a  b  c
    0  1  2  0
    1  2  1  0
    

    这应该会快得多,因为它不需要为每一行调用一次 encoder.fit_transform(如果你有很多行,这可能会导致糟糕的性能)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-20
      • 1970-01-01
      • 1970-01-01
      • 2018-11-04
      • 2022-06-21
      • 1970-01-01
      相关资源
      最近更新 更多