多列使用相同类别进行标签编码

4
考虑以下数据框:
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
4个回答

3
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(如果你有很多行可能会导致性能恶劣)。


2
您可以使用pd.factorize来完成此操作。
df = df.stack()
df[:] = pd.factorize(df)[0]
df.unstack()

   a  b  c
0  0  1  2
1  1  0  2

如果你只想对数据框中的某些列进行编码,那么可以按照以下步骤操作:

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
@Martin:请检查一下您原始的df是否有错别字,特别是第二行的“意大利”。 - unutbu
你说得对,是我的错。我忘记在第一行中尝试用瑞典替换意大利了。我的问题意思是应该适用于所有行,而第一个答案中的第二种方法确实可以做到,尽管现在我能看到我的定义有歧义。 - Martin

1
如果编码顺序不重要,您可以这样做:

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

有没有办法在这里获取映射?另外,我认为您在此处解决了一个问题。 - Christopher

0

这里有一个使用分类数据的替代方案。与@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() 做的不就是同样的事情吗? - Bharath M Shetty
@Dark,没错。你选择这种解决方案的唯一原因是你打算使用分类特征(例如验证),而代码视图只是另一种替代表示形式。 - jpp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接