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

时间:2015-05-16 05:24:51

标签: pandas fill sparse-matrix

我有一个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()

2 个答案:

答案 0 :(得分:1)

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

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

之后,您可以添加其他变量,但所有内容都必须是数字。大熊猫稀疏数据帧只是稀疏(和同质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

对于小型示例数据帧,这里没有太多的节省,但可能与实际数据帧有很大差异。

答案 1 :(得分:0)

我以前曾解决过类似的问题。我所做的是,我之前应用了 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_'))

希望这可以帮助某人!