Проблемы с бинарным one-hot (one-of-K) кодированием в python

Двоичное горячее (также известное как one-of-K) кодирование заключается в создании одного двоичного столбца для каждого отдельного значения категориальной переменной. Например, если есть столбец цвета (категориальная переменная), который принимает значения «красный», «синий», «желтый» и «неизвестно», то двоичное прямое кодирование заменяет столбец цвета двоичными столбцами «цвет = красный», «цвет = синий» и «цвет = желтый». Я начинаю с данных в кадре данных pandas, и я хочу использовать эти данные для обучения модели с помощью scikit-learn. Я знаю два способа сделать бинарное однократное кодирование, и ни один из них меня не удовлетворил.

  1. Pandas и get_dummies в категориальных столбцах фрейма данных. Этот метод кажется превосходным, поскольку исходный фрейм данных содержит все доступные данные. То есть вы выполняете однократное горячее кодирование перед разделением данных на обучающие, проверочные и тестовые наборы. Однако, если данные уже разбиты на разные наборы, этот метод работает не очень хорошо. Почему? Потому что один из наборов данных (скажем, тестовый) может содержать меньше значений для данной переменной. Например, может случиться так, что обучающий набор содержит значения красного, синего, желтого и неизвестного для переменной цвета, а тестовый набор содержит только красный и синий. Таким образом, в тестовом наборе будет меньше столбцов, чем в обучающем наборе. (Я также не знаю, как сортируются новые столбцы, и даже если они имеют одинаковые столбцы, это может быть в другом порядке в каждом наборе).

  2. Sklearn и DictVectorizer Это решает предыдущую проблему, поскольку мы можем быть уверены, что применяем то же самое преобразование к тестовому набору. Однако результатом преобразования является массив numpy вместо кадра данных pandas. Если мы хотим восстановить вывод в виде кадра данных pandas, нам нужно (или, по крайней мере, так я это делаю): 1) pandas.DataFrame(data=результат преобразования DictVectorizer, index=index исходных данных pandas frame, columns= DictVectorizer().get_features_names) и 2) соединить по индексу полученный фрейм данных с исходным, содержащим числовые столбцы. Это работает, но несколько громоздко.

Есть ли лучший способ выполнить бинарное однократное кодирование в фрейме данных pandas, если у нас есть данные, разделенные на обучающий и тестовый наборы?


person drake    schedule 27.08.2015    source источник
comment
Ну, что я делаю, так это объединяю dfs, использую get_dummies, а затем снова разделяю их, например, encoded = pd.get_dummies(pd.concat([train,test], axis=0)) train_encoded = encoded.iloc[:train.shape[0], :] test_encoded = encoded.iloc[train.shape[0]:, :]   -  person inversion    schedule 27.08.2015
comment
Но, с другой стороны, если ваши столбцы не в том же порядке, то мое предложение не сработает.   -  person inversion    schedule 27.08.2015
comment
Спасибо, @inversion Почему бы вам не превратить свой комментарий в ответ?   -  person drake    schedule 28.08.2015


Ответы (2)


Если ваши столбцы находятся в том же порядке, вы можете объединить dfs, использовать get_dummies, а затем снова разделить их, например,

encoded = pd.get_dummies(pd.concat([train,test], axis=0))
train_rows = train.shape[0]
train_encoded = encoded.iloc[:train_rows, :]
test_encoded = encoded.iloc[train_rows:, :] 

Если ваши столбцы расположены не в том же порядке, у вас будут проблемы независимо от того, какой метод вы попробуете.

person inversion    schedule 28.08.2015

Вы можете установить тип данных как категориальный:

In [5]: df_train = pd.DataFrame({"car":Series(["seat","bmw"]).astype('category',categories=['seat','bmw','mercedes']),"color":["red","green"]})

In [6]: df_train
Out[6]: 
    car  color
0  seat    red
1   bmw  green

In [7]: pd.get_dummies(df_train )
Out[7]: 
   car_seat  car_bmw  car_mercedes  color_green  color_red
0         1        0             0            0          1
1         0        1             0            1          0

См. эту проблему Pandas.

person Tarantula    schedule 10.11.2015