2015-12-22 78 views
2

我知道使用包熊貓可以很容易地實現它,但是因爲它太稀疏和很大(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 

更新:

現在我在這裏,和「身份證」丟失,怎麼辦聚集呢?

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

你可以做一個數據幀的類別爲您展示,然後使用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是排在第三(與索引值2)。這已映射到c,您可以從反向映射中看到中間的列。它也是矩陣中間列中唯一包含值1的值,用於確認結果。

除此之外,我不確定你會卡在哪裏。如果您仍有問題,請澄清。

要連接的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()''之後的原始問題中顯示的那個。必須是稀疏矩陣,否則會佔用太多內存。順便說一句,我用真實的數據集嘗試了熊貓的方式,而'groupby'步驟需要幾天時間,所以在放棄之前我放棄了。 – Chen