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_'))
希望这对某人有所帮助!
我有一个 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_'))
希望这对某人有所帮助!