2

パッケージ pandas を使えば簡単に実現できることはわかっているのですが、あまりにもまばらで大きい (170,000 x 5000) ため、最後に sklearn を使用して再度データを処理する必要があるため、 sklearnで行う方法。ワンホットエンコーダーを試しましたが、ダミーを「id」に関連付けるのに行き詰まりました。

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

アップデート:

今、私はここにいて、「id」が失われました。集計を行うにはどうすればよいですか?

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.]])
4

2 に答える 2

1

将来誰かが参照を必要とする場合に備えて、ここに私の解決策を示します。scipy 疎行列を使用しました。

まず、グループ化を行い、レコード数を数えます。

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

これには時間がかかりますが、数日ではありません。

次に、ここで解決策を見つけたピボット テーブルを使用します。

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')
于 2016-05-05T03:16:33.857 に答える
0

OneHotEncoder は整数を必要とするため、アイテムを一意の整数にマップする 1 つの方法を次に示します。マッピングは 1 対 1 であるため、この辞書を逆にすることもできます。

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が 3 行目にあることがわかります (インデックス値は 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.]])
于 2015-12-22T05:09:46.057 に答える