pandas 或 scipy 中的 groupby.sum() 稀疏矩阵:寻找性能

swe*_*eet 5 performance numpy scipy sparse-matrix pandas

我有以下数据集df

import numpy.random
import pandas

cat = pandas.Series(numpy.random.random_integers(0,400,1000000))
ids = pandas.Series(numpy.random.random_integers(0,10000,1000000))
team = pandas.Series(numpy.random.random_integers(0,1,1000000))
df = pandas.concat([ids,cat,team],axis=1)
df.columns = ['ids','cat','team']
Run Code Online (Sandbox Code Playgroud)

请注意,该列中只有 400 个不同的类别cat。因此,我想为机器学习分类准备数据集,即为 0 到 400 之间的每个不同类别值创建一列,对于每一行,如果 id 具有相应的类别,则写入 1,否则写入 0。我的目标是创建一个 groupby ids,并对每个类别列的 1 求和,如下所示:

df2 = pandas.get_dummies(df['cat'], sparse=True)
df2['ids'] = df['ids']
df3 = df2.groupby('ids').sum()
Run Code Online (Sandbox Code Playgroud)

我的问题是它groupby.sum()非常非常长,太长了(超过 30 分钟)。所以我需要一个不同的策略来进行计算。这是第二次尝试。

from sklearn import preprocessing
import numpy

text_encoder = preprocessing.OneHotEncoder(dtype=numpy.int)
X = text_encoder.fit_transform(df.drop(['team','ids'],axis=1).values).astype(int)
Run Code Online (Sandbox Code Playgroud)

但是,X是一个稀疏的 scipy 矩阵。这里我有两个选择:要么找到一种groupby.sum()有效处理这个稀疏 scipy 矩阵的方法,要么将其转换为真正的 numpy 矩阵,.toarray()如下所示:

X = X.toarray()
df2 = pandas.DataFrame(X)
df2['ids'] = df['ids']
df3 = df2.groupby('ids').sum()
Run Code Online (Sandbox Code Playgroud)

现在的问题是,由于.toarray(). 而且groupby.sum()肯定需要大量内存。

所以我的问题是:有没有一种聪明的方法可以使用稀疏矩阵和高效的时间来解决我的问题groupby.sum()

etn*_*tna 3

编辑:事实上这是pivot_table()的工作,所以一旦df创建:

df_final = df.pivot_table(cols='cat', rows='ids', aggfunc='count')
df_final.fillna(0, inplace = True)
Run Code Online (Sandbox Code Playgroud)

作为记录,但没用:按照我对这个问题的评论:

import numpy.random
import pandas
from sklearn import preprocessing

cat = pandas.Series(numpy.random.random_integers(0,400,1000000))
ids = pandas.Series(numpy.random.random_integers(0,10000,1000000))
team = pandas.Series(numpy.random.random_integers(0,1,1000000))
df = pandas.concat([ids,cat,team],axis=1)
df.columns = ['ids','cat','team']

df.sort('ids', inplace = True)

text_encoder = preprocessing.OneHotEncoder(dtype=numpy.int)
X = text_encoder.fit_transform(df.drop(['team','ids'],axis=1).values).astype(int)

se_size = df.groupby('ids').size()

ls_rows = []
row_ind = 0
for name, nb_lines in se_size.iteritems():
  ls_rows.append(X[row_ind : row_ind + nb_lines,:].sum(0).tolist()[0])
  row_ind += nb_lines
df_final = pandas.DataFrame(ls_rows,
                            index = se_size.index,
                            columns = text_encoder.active_features_)
Run Code Online (Sandbox Code Playgroud)