【发布时间】:2014-02-08 10:01:51
【问题描述】:
我正在对 DataFrame 执行复杂的转换。我认为这对 Pandas 来说会很快,但我设法做到这一点的唯一方法是使用一些嵌套的 groupbys 和 apply,使用 lambda 函数,而且速度很慢。似乎应该有内置的、更快的方法。在 n_rows=1000 是 2 秒,但我会做 10^7 行,所以这太慢了。很难解释我们在做什么,所以这里是代码和配置文件,然后我会解释:
n_rows = 1000
d = pd.DataFrame(randint(1,10,(n_rows,8))) #Raw data
dgs = array([3,4,1,8,9,2,3,7,10,8]) #Values we will look up, referenced by index
grps = pd.cut(randint(1,5,n_rows),arange(1,5)) #Grouping
f = lambda x: dgs[x.index].mean() #Works on a grouped Series
g = lambda x: x.groupby(x).apply(f) #Works on a Series
h = lambda x: x.apply(g,axis=1).mean(axis=0) #Works on a grouped DataFrame
q = d.groupby(grps).apply(h) #Slow
824984 function calls (816675 primitive calls) in 1.850 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
221770 0.105 0.000 0.105 0.000 {isinstance}
7329 0.104 0.000 0.217 0.000 index.py:86(__new__)
8309 0.089 0.000 0.423 0.000 series.py:430(__new__)
5375 0.081 0.000 0.081 0.000 {method 'reduce' of 'numpy.ufunc' objects}
34225 0.068 0.000 0.133 0.000 {method 'view' of 'numpy.ndarray' objects}
36780/36779 0.067 0.000 0.067 0.000 {numpy.core.multiarray.array}
5349 0.065 0.000 0.567 0.000 series.py:709(_get_values)
985/1 0.063 0.000 1.847 1.847 groupby.py:608(apply)
5349 0.056 0.000 0.198 0.000 _methods.py:42(_mean)
5358 0.050 0.000 0.232 0.000 index.py:332(__getitem__)
8309 0.049 0.000 0.228 0.000 series.py:3299(_sanitize_array)
9296 0.047 0.000 0.116 0.000 index.py:1341(__new__)
984 0.039 0.000 0.092 0.000 algorithms.py:105(factorize)
按分组对 DataFrame 行进行分组。对于每个分组,对于每一行,按相同的值进行分组(即,所有的值都为 3,而所有的值都为 4)。对于值分组中的每个索引,在dgs 中查找对应的索引,并取平均值。然后对行分组进行平均。
::呼气::
任何关于如何重新排列以提高速度的建议都将不胜感激。
【问题讨论】:
-
像这样进行嵌套的嵌套应用/分组不是答案。这几乎是纯 python 代码,你没有利用任何 pandas 的优势。您可能希望在顶层进行分组(或构建多索引),选择要包含的值,然后使用 cythonized 函数应用它。您只想做 1 级 groupby 并申请(在一些非常罕见的情况下除外)。你最终是在做一些向量化的操作,但你是在最低级别向后做的。