如何创建虚拟变量然后使用 scikit-learn 进行聚合?

Posted

技术标签:

【中文标题】如何创建虚拟变量然后使用 scikit-learn 进行聚合?【英文标题】:How to create dummy variable and then aggregate using scikit-learn? 【发布时间】:2016-03-28 06:02:48 【问题描述】:

我知道使用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.]])

【问题讨论】:

您可以在显示的数据框中执行类别,然后使用 as_matrix() 方法转换为 numpy 数组表示形式吗? @SteveMisuta 是的,我可以做到。能否详细说明原因? @Chen 你有想过这个问题吗? @Afflatus,我想我最后转向了 scipy 稀疏矩阵。首先使用df.groupby(['id','item']).size().reset_index().rename(columns=0:'count'),这需要一些时间而不是几天。然后使用数据透视表,可以找到here。满足了我当时的需要。希望对您有所帮助,有任何意见,请告诉我。 谢谢!!!这非常有帮助。 【参考方案1】:

如果将来有人需要参考,我将我的解决方案放在这里。 我使用了 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')

【讨论】:

【参考方案2】:

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

【讨论】:

谢谢你的回答,我被困在根据那些'id'的聚合上。有关详细信息,请参阅原始问题中的更新。 你想要的输出是什么? 类似于我在原始问题中 dummy.groupby('id').sum().reset_index() 之后显示的那个。必须是稀疏矩阵,否则会占用太多内存。顺便说一句,我在真实数据集上尝试了 pandas 方式,而 groupby 步骤需要几天时间,所以我在完成之前放弃了。

以上是关于如何创建虚拟变量然后使用 scikit-learn 进行聚合?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止一个高度相关的变量淹没 scikit-learn 中的其余变量?

如何使用 scikit-learn 创建我自己的数据集?

如何删除python的虚拟环境

如何保持一个高度相关的变量在scikit-learn中淹没其余部分?

给定参考值的二维矩阵,对两个变量进行 Scikit-learn 回归

scikit-learn 对整数变量的解释