2015-12-22 6 views
2

Я знаю, что это можно легко реализовать с помощью пакета pandas, но поскольку он слишком редок и большой (170 000 x 5000), и в конце мне нужно использовать sklearn для обработки данных снова, мне интересно, это способ сделать с sklearn. Я попробовал один горячий кодер, но застрял, чтобы связать манекены с «id».Как создать фиктивную переменную, а затем агрегировать с помощью scikit-learn?

df = pd.DataFrame({'id': [1, 1, 2, 2, 3, 3], 'item': ['a', 'a', 'c', 'b', 'a', 'b']}) 

    id item 
0 1 a 
1 1 a 
2 2 c 
3 2 b 
4 3 a 
5 3 b 

dummy = pd.get_dummies(df, prefix='item', columns=['item']) 
dummy.groupby('id').sum().reset_index() 

    id item_a item_b item_c 
0 1  2  0  0 
1 2  0  1  1 
2 3  1  1  0 

Update:

Теперь я здесь, и 'идентификатор' теряется, как сделать агрегацию тогда?

lab = sklearn.preprocessing.LabelEncoder() 
labels = lab.fit_transform(np.array(df.item)) 
enc = sklearn.preprocessing.OneHotEncoder() 
dummy = enc.fit_transform(labels.reshape(-1,1)) 

dummy.todense() 

matrix([[ 1., 0., 0.], 
     [ 1., 0., 0.], 
     [ 0., 0., 1.], 
     [ 0., 1., 0.], 
     [ 1., 0., 0.], 
     [ 0., 1., 0.]]) 
+0

Вы можете сделать категории в dataframe, как вы показываете, а затем использовать метод as_matrix() для преобразования в Numpy представления массива? –

+0

@SteveMisuta Да, я могу это сделать. Не могли бы вы объяснить причину? – Chen

+0

@Chen Вы когда-нибудь поняли это? – Afflatus

ответ

2

В случае, если кто нуждается в ссылке в будущем, я положил мое решение здесь. Я использовал scipy редкую матрицу.

Сначала сделайте группировку и подсчитайте количество записей.

df = df.groupby(['id','item']).size().reset_index().rename(columns={0:'count'}) 

Это занимает некоторое время, но не дней.

Затем используйте сводную таблицу, в которой я нашел решение here.

from scipy.sparse import csr_matrix 

def to_sparse_pivot(df, id, item, count): 
    id_u = list(df[id].unique()) 
    item_u = list(np.sort(df[item].unique())) 
    data = df[count].tolist() 
    row = df[id].astype('category', categories=id_u).cat.codes 
    col = df[item].astype('category', categories=item_u).cat.codes 
    return csr_matrix((data, (row, col)), shape=(len(id_u), len(item_u))) 

Затем вызовите функцию

result = to_sparse_pivot(df, 'id', 'item', 'count') 
0

OneHotEncoder требует целых чисел, так что это один из способов сопоставить элементы с уникальным целым числом. Поскольку отображение является взаимно-однозначным, мы также можем отменить этот словарь.

import pandas as pd 
from sklearn.preprocessing import OneHotEncoder 

df = pd.DataFrame({'ID': [1, 1, 2, 2, 3, 3], 
        'Item': ['a', 'a', 'c', 'b', 'a', 'b']}) 

mapping = {letter: integer for integer, letter in enumerate(df.Item.unique())} 
reverse_mapping = {integer: letter for letter, integer in mapping.iteritems()} 

>>> mapping 
{'a': 0, 'b': 2, 'c': 1} 

>>> reverse_mapping 
{0: 'a', 1: 'c', 2: 'b'} 

Теперь создайте OneHotEncoder и сориентируйте свои значения.

hot = OneHotEncoder() 
h = hot.fit_transform(df.Item.map(mapping).values.reshape(len(df), 1)) 
>>> h 
<6x3 sparse matrix of type '<type 'numpy.float64'>' 
    with 6 stored elements in Compressed Sparse Row format> 
>>> h.toarray() 
array([[ 1., 0., 0.], 
     [ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.], 
     [ 1., 0., 0.], 
     [ 0., 0., 1.]]) 

И для справки, они были бы соответствующие колонки:

>>> [reverse_mapping[n] for n in reverse_mapping.keys()] 
['a', 'c', 'b'] 

Из данных, вы можете увидеть, что значение c в dataframe был в третьем ряду (со значением индекса 2). Это сопоставимо с c, которое вы можете видеть по обратному отображению, это средний столбец. Это также единственное значение в среднем столбце матрицы, которое содержит значение единицы, подтверждающее результат.

Помимо этого, я не уверен, где вы застряли. Если у вас все еще есть проблемы, уточните пожалуйста.

Объединяет значение ID:

>>> np.concatenate((df.ID.values.reshape(len(df), 1), h.toarray()), axis=1) 
array([[ 1., 1., 0., 0.], 
     [ 1., 1., 0., 0.], 
     [ 2., 0., 1., 0.], 
     [ 2., 0., 0., 1.], 
     [ 3., 1., 0., 0.], 
     [ 3., 0., 0., 1.]]) 

Чтобы сохранить массив разреженный:

from scipy.sparse import hstack, lil_matrix 

id_vals = lil_matrix(df.ID.values.reshape(len(df), 1)) 
h_dense = hstack([id_vals, h.tolil()]) 
>>> type(h_dense) 
scipy.sparse.coo.coo_matrix 

>>> h_dense.toarray() 
array([[ 1., 1., 0., 0.], 
     [ 1., 1., 0., 0.], 
     [ 2., 0., 1., 0.], 
     [ 2., 0., 0., 1.], 
     [ 3., 1., 0., 0.], 
     [ 3., 0., 0., 1.]]) 
+0

Спасибо за ваш ответ, я застрял на агрегации в соответствии с этими «идентификаторами». Пожалуйста, ознакомьтесь с обновлением в оригинальном вопросе. – Chen

+0

Каков ваш желаемый результат? – Alexander

+0

Что-то вроде того, что я показал в исходном вопросе после 'dummy.groupby ('id'). Sum(). Reset_index()'. Должна быть разреженной матрицей, иначе это займет слишком много памяти. Кстати, я пробовал использовать pandas с реальными наборами данных, а для «группового» шага требуется несколько дней, поэтому я сдался, прежде чем он смог закончить. – Chen