如何创建虚拟变量然后使用 scikit-learn 进行聚合?
How to create dummy variable and then aggregate using scikit-learn?
我知道使用包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.]])
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.]])
以防以后有人需要参考,我把我的解决方案放在这里。
我使用了 scipy 稀疏矩阵。
首先进行分组,统计记录数
df = df.groupby(['id','item']).size().reset_index().rename(columns={0:'count'})
这需要一些时间而不是几天。
然后使用 pivot table,我找到了一个解决方案 。
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')
我知道使用包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.]])
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.]])
以防以后有人需要参考,我把我的解决方案放在这里。 我使用了 scipy 稀疏矩阵。
首先进行分组,统计记录数
df = df.groupby(['id','item']).size().reset_index().rename(columns={0:'count'})
这需要一些时间而不是几天。
然后使用 pivot table,我找到了一个解决方案
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')