Метка, кодирующая несколько столбцов с одинаковой категорией
Рассмотрим следующий кадр данных:
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 ответа
Проходить 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
Введите и используйте коды категорий в качестве меток:
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
один раз для каждой строки (что может привести к ужасной производительности, если у вас много строк).
Вы можете сделать это с 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
Если порядок кодирования не имеет значения, вы можете сделать:
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
Вот альтернативное решение с использованием категориальных данных. Подобно @unutbu's, но сохраняет порядок факторизации. Другими словами, первое найденное значение будет иметь код 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