Кодирование меток в нескольких столбцах с одинаковыми атрибутами в sckit-learn - PullRequest
0 голосов
/ 10 мая 2018

Если у меня есть два столбца, как показано ниже:

Origin  Destination  
China   USA  
China   Turkey  
USA     China  
USA     Turkey  
USA     Russia  
Russia  China  

Как мне выполнить кодирование метки, при этом метка для столбца происхождения совпадает с меткой в ​​столбце назначения, т. Е.

Origin  Destination  
0   1  
0   3  
1   0  
1   0  
1   0  
2   1  

Если я сделаю кодирование для каждого столбца в отдельности, тогда алгоритм увидит, что Китай в столбце 1 отличается от столбца 2, что не так

Ответы [ 5 ]

0 голосов
/ 10 мая 2018

Используя LabelEncoder из sklearn, вы также можете попробовать:

from sklearn import preprocessing

le = preprocessing.LabelEncoder()
le.fit(df.values.flatten())

df = df.apply(le.fit_transform)
print(df)

Результат:

   Origin  Destination
0       0            3
1       0            2
2       2            0
3       2            2
4       2            1
5       1            0

Если у вас есть больше столбцов и вы хотите применить их только к выбранным столбцам данных, то вы можете попробовать:

from sklearn import preprocessing
le = preprocessing.LabelEncoder()

# columns to select for encoding
selected_col = ['Origin','Destination']
le.fit(df[selected_col].values.flatten())

df[selected_col] = df[selected_col].apply(le.fit_transform)
print(df)
0 голосов
/ 10 мая 2018

Редактировать: только что узнал о return_inverse опции для np.unique. Не нужно искать и подставлять!

df.values[:] = np.unique(df, return_inverse=True)[1].reshape(-1,2)

Вы можете использовать векторизованную версию np.searchsorted с

df.values[:] = np.searchsorted(np.sort(np.unique(df)), df)

Или вы можете создать массив кодировок для одной операции и восстановить индексы с помощью argmax. Вероятно, не очень хорошая идея, если есть много стран.

df.values[:] = (df.values[...,None] == np.unique(df)).argmax(-1)
0 голосов
/ 10 мая 2018

pandas Метод

Вы можете создать словарь из {country: value} пар и отобразить кадр данных на него:

country_map = {country:i for i, country in enumerate(df.stack().unique())}

df['Origin'] = df['Origin'].map(country_map)    
df['Destination'] = df['Destination'].map(country_map)

>>> df
   Origin  Destination
0       0            1
1       0            2
2       1            0
3       1            2
4       1            3
5       3            0

sklearn метод

Поскольку вы пометили sklearn, вы можете использовать LabelEncoder():

from sklearn.preprocessing import LabelEncoder
le= LabelEncoder()
le.fit(df.stack().unique())

df['Origin'] = le.transform(df['Origin'])
df['Destination'] = le.transform(df['Destination'])

>>> df
   Origin  Destination
0       0            3
1       0            2
2       3            0
3       3            2
4       3            1
5       1            0

Для возврата оригинальных этикеток:

>>> le.inverse_transform(df['Origin'])
# array(['China', 'China', 'USA', 'USA', 'USA', 'Russia'], dtype=object)
0 голосов
/ 10 мая 2018

Вы можете использовать replace

df.replace(dict(zip(np.unique(df.values),list(range(len(np.unique(df.values)))))))
   Origin  Destination
0       0            3
1       0            2
2       3            0
3       3            2
4       3            1
5       1            0

Сжатый и приятный ответ от Пир

df.replace((lambda u: dict(zip(u, range(u.size))))(np.unique(df)))

И

df.replace(dict(zip(np.unique(df), itertools.count())))
0 голосов
/ 10 мая 2018

stack

df.stack().pipe(lambda s: pd.Series(pd.factorize(s.values)[0], s.index)).unstack()

   Origin  Destination
0       0            1
1       0            2
2       1            0
3       1            2
4       1            3
5       3            0

factorize с reshape

pd.DataFrame(
    pd.factorize(df.values.ravel())[0].reshape(df.shape),
    df.index, df.columns
)

   Origin  Destination
0       0            1
1       0            2
2       1            0
3       1            2
4       1            3
5       3            0

np.unique и reshape

pd.DataFrame(
    np.unique(df.values.ravel(), return_inverse=True)[1].reshape(df.shape),
    df.index, df.columns
)

   Origin  Destination
0       0            3
1       0            2
2       3            0
3       3            2
4       3            1
5       1            0

Отвратительный вариант

Я не мог перестать пытаться что-то ... извините!

df.applymap(
    lambda x, y={}, c=itertools.count():
        y.get(x) if x in y else y.setdefault(x, next(c))
)

   Origin  Destination
0       0            1
1       0            3
2       1            0
3       1            3
4       1            2
5       2            0

Как указано cᴏʟᴅsᴘᴇᴇᴅ

Вы можете сократить это, назначив обратно кадру данных

df[:] = pd.factorize(df.values.ravel())[0].reshape(df.shape)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...