1

У меня есть список, как похож на это:Один горячее кодирование категорий

list = ['Opinion, Journal, Editorial', 
     'Opinion, Magazine, Evidence-based', 
     'Evidence-based'] 

где запятые раскол между категориями например. Мнение и журнал - две отдельные категории. Реальный список намного больше и имеет более возможные категории. Я хотел бы использовать однострунную кодировку для преобразования списка, чтобы его можно было использовать для машинного обучения. Например, из этого списка я хотел бы произвести разреженную матрицу, содержащую данные, такие как:

list = [[1, 1, 1, 0, 0], 
     [1, 0, 0, 0, 1], 
     [0, 0, 0, 0, 1]] 

В идеале я хотел бы использовать scikit-learn's one hot encoder, как я полагаю, это будет наиболее эффективным.

В ответ на комментарий @nbrayns:

Идея заключается в том, чтобы преобразовать список категорий из текста в векторе wherby, если он принадлежит к этой категории он будет назначен 1, в противном случае 0. Для приведенного выше примера, то которые должны быть указаны:

headings = ['Opinion', 'Journal', 'Editorial', 'Magazine', 'Evidence-based'] 
+0

Какие значения должны быть 1, а что должно быть 0? – nbryans

+0

@nbryans Редактировать вопрос. – user7347576

ответ

0

Это может быть не самый эффективный метод, но, вероятно, его легко понять.
Если у вас еще нет списка всех возможных слов, вам нужно создать это. В приведенном ниже коде он называется unique. Затем столбцы выходной матрицы s будут соответствовать этим уникальным словам; строки будут элементом из списка.

import numpy as np 

lis = ['Opinion, Journal, Editorial','Opinion, Magazine, Evidence-based','Evidence-based'] 

unique=list(set(", ".join(lis).split(", "))) 
print unique 
# prints ['Opinion', 'Journal', 'Magazine', 'Editorial', 'Evidence-based'] 

s = np.zeros((len(lis), len(unique))) 
for i, item in enumerate(lis): 
    for j, notion in enumerate(unique): 
     if notion in item: 
      s[i,j] = 1 

print s 
# prints [[ 1. 1. 0. 1. 0.] 
#   [ 1. 0. 1. 0. 1.] 
#   [ 0. 0. 0. 0. 1.]] 
-1

Очень легко в pandas:

import pandas as pd 
s = pd.Series(['a','b','c']) 
pd.get_dummies(s) 

Выход:

a b c 
0 1 0 0 
1 0 1 0 
2 0 0 1 
0

Еще один способ:

l = ['Opinion, Journal, Editorial', 'Opinion, Magazine, Evidence-based', 'Evidence-based'] 

# Get list of unique classes 
classes = list(set([j for i in l for j in i.split(', ')])) 
=> ['Journal', 'Opinion', 'Editorial', 'Evidence-based', 'Magazine'] 

# Get indices in the matrix 
indices = np.array([[k, classes.index(j)] for k, i in enumerate(l) for j in i.split(', ')]) 
=> array([[0, 1], 
      [0, 0], 
      [0, 2], 
      [1, 1], 
      [1, 4], 
      [1, 3], 
      [2, 3]]) 

# Generate output 
output = np.zeros((len(l), len(classes)), dtype=int) 
output[indices[:, 0], indices[:, 1]]=1 
=> array([[ 1, 1, 1, 0, 0], 
      [ 0, 1, 0, 1, 1], 
      [ 0, 0, 0, 1, 0]]) 
3

Если вы можете использовать панд, эта функциональность по существу встроенный:

import pandas as pd 

l = ['Opinion, Journal, Editorial', 'Opinion, Magazine, Evidence-based', 'Evidence-based'] 
pd.Series(l).str.get_dummies(', ') 
Editorial Evidence-based Journal Magazine Opinion 
0   1    0  1   0  1 
1   0    1  0   1  1 
2   0    1  0   0  0 

Если вы хотите придерживаться sklearn экосистемы, которую вы ищете MultiLabelBinarizer, не OneHotEncoder. Как следует из названия, OneHotEncoder поддерживает только один уровень на выборку для каждой категории, в то время как ваш набор данных имеет несколько.

from sklearn.preprocessing import MultiLabelBinarizer 

mlb = MultiLabelBinarizer() # pass sparse_output=True if you'd like 
mlb.fit_transform(s.split(', ') for s in l) 
[[1 0 1 0 1] 
[0 1 0 1 1] 
[0 1 0 0 0]] 

Чтобы отобразить столбцы обратно категориальных уровней, вы можете получить доступ к mlb.classes_. В приведенном выше примере это дает ['Editorial' 'Evidence-based' 'Journal' 'Magazine' 'Opinion'].

+0

Будет ли это работать независимо от порядка категорий? – user7347576

+1

@ user7347576 Да, если вы спрашиваете, имеет ли значение «Мнение, журнал» или «Журнал, мнение», это не так. –