pandas 中稀疏矩阵的 groupby:首先填充它们

groupby on sparse matrix in pandas: filling them first

我有一个 pandas DataFrame df 形状为 (1000000,3) 如下:

id      cat       team
1       'cat1'    A
1       'cat2'    A
2       'cat3'    B
3       'cat1'    A
4       'cat3'    B
4       'cat1'    B

然后我对 cat 列进行虚拟化,以便为机器学习分类做好准备。

df2 = pandas.get_dummies(df,columns=['cat'], sparse=True)

但是当我尝试这样做时:

df2.groupby(['id','team']).sum()

它卡住了,计算永无止境。因此,我没有立即分组,而是尝试:

df2 = df2.fillna(0)

但它不起作用,DataFrame 仍然充满了 NaN 个值。为什么 fillna() 函数没有按预期填充我的 DataFrame? 换句话说,我从 get_dummies 得到的 pandas 稀疏矩阵如何填充 0 而不是 NaN?

我也试过:

df2 = pandas.get_dummies(df,columns=['cat'], sparse=True).to_sparse(fill_value=0)

这次df2填0很好,但是当我尝试的时候:

print df2.groupby(['id','sexe']).sum()

我得到:

C:\Anaconda\lib\site-packages\pandas\core\groupby.pyc in loop(labels, shape)
   3545         for i in range(1, nlev):
   3546             stride //= shape[i]
-> 3547             out += labels[i] * stride
   3548 
   3549         if xnull: # exclude nulls
ValueError: operands could not be broadcast together with shapes (1205800,) (306994,) (1205800,) 

我的解决方案是:

df2 = pandas.DataFrame(np.nan_to_num(df2.as_matrix()))
df2.groupby(['id','sexe']).sum()

它确实有效,但它需要大量内存。有人可以帮我找到更好的解决方案,或者至少理解为什么我不能轻易用零填充稀疏矩阵吗?为什么不可能在稀疏矩阵上使用 groupby() 然后 sum()

我认为你的问题是由于数据类型的混合。但是你可以像这样绕过它。首先,仅向 get_dummies() 提供相关列而不是整个数据框:

df2 = pd.get_dummies(df['cat']).to_sparse(0)

之后,您可以添加其他变量,但所有变量都必须是数字。 pandas 稀疏数据框只是对稀疏(和同质 dtype)numpy 数组的包装。

df2['id'] = df['id']

   'cat1'  'cat2'  'cat3'  id
0       1       0       0   1
1       0       1       0   1
2       0       0       1   2
3       1       0       0   3
4       0       0       1   4
5       1       0       0   4

对于非数字类型,您可以执行以下操作:

df2['team'] = df['team'].astype('category').cat.codes

这个 groupby 似乎工作正常:

df2.groupby('id').sum()

    'cat1'  'cat2'  'cat3'
id                        
1        1       1       0
2        0       0       1
3        1       0       0
4        1       0       1

内存管理的另一个但可能很重要的一点是,您通常可以使用分类而不是字符串对象来节省大量内存(虽然您可能已经在这样做了):

df['cat2'] = df['cat'].astype('category')

df[['cat','cat2']].memory_usage()

cat     48
cat2    30

对于小型示例数据框,这里节省的不多,但在您的实际数据框中可能会有很大的不同。

我之前也遇到过类似的问题。我所做的是,我在 之前应用了 groupby 操作,然后 跟进了 get_dummies().

这对我有用,因为 groupby 在形成数千个虚拟列(在我的例子中)之后非常慢,尤其是在稀疏数据帧上。它基本上放弃了我。首先对列进行分组,然后进行虚拟化使其工作。

df = pd.DataFrame(df.groupby(['id','team'])['cat'].unique())
df.columns = ['cat']
df.reset_index(inplace=True)
df = df[['id','team']].join(df['cat'].str.join('|').str.get_dummies().add_prefix('CAT_'))

希望这对某人有所帮助!