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

时间:2015-05-18 05:17:04

标签: performance numpy pandas scipy sparse-matrix

我有以下数据集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']

请注意,cat列中只有400个不同的类别。因此,我想为机器学习分类准备数据集,即为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()

我的问题是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)

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

X = X.toarray()
df2 = pandas.DataFrame(X)
df2['ids'] = df['ids']
df3 = df2.groupby('ids').sum()

现在的问题是由于.toarray()导致大量内存丢失。 groupby.sum()肯定需要很多记忆。

所以我的问题是:有没有一种聪明的方法来解决我的问题,使用SPARSE MATRIX和groupby.sum()的有效时间?

1 个答案:

答案 0 :(得分:2)

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

df_final = df.pivot_table(cols='cat', rows='ids', aggfunc='count')
df_final.fillna(0, inplace = True)

记录但没用:跟我对这个问题的评论:

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_)