编辑添加:由于在0.17.0版本的pandas中进行了GIL解锁(以及自0.14.1及更早版本以来的其他改进),此操作似乎得到了极大的改进。请参阅此问题底部的更新基准。
这是对此非常有用的问答的跟进:Faster way to transform group with mean value in Pandas
我刚刚从14.0更新到14.1,看看groupby / transform操作有多大改进。简而言之,这种改进是实质性的,但它仍然比解决方法慢得多,并且对于我正在使用的数据基本上无法使用。
这是一个例子,每组有10万名盲人,每组3名:
df = DataFrame( { 'id' : np.arange( 100000 ) / 3,
'val': np.random.randn( 100000) } )
grp=df.groupby('id')['val']
a = pd.Series(np.repeat(grp.mean().values, grp.count().values))
b = grp.transform(np.mean)
“a”是E先生和杰夫的绝佳解决方法(见上文链接),我非常感激,“b”是我认为这种情况的标准方法。
In [42]: (a==b).all()
Out[42]: True
In [43]: %timeit pd.Series(np.repeat(grp.mean().values, grp.count().values))
100 loops, best of 3: 3.34 ms per loop
In [44]: %timeit grp.transform(np.mean)
1 loops, best of 3: 4.61 s per loop
注意“ms”vs“s”所以1000x差异!我试着在这里小心并做一个公平的比较。如果我以某种方式搞砸了,请告诉我。我不太了解numpy / pandas内部,但是假设它们都使用相同的底层np.mean函数?
更多信息:
In [61]: %timeit grp.transform('mean')
1 loops, best of 3: 4.59 s per loop
In [62]: pd.__version__
Out[62]: '0.14.1'
~/google drive/data>python -V
Python 2.7.8 :: Anaconda 2.0.1 (x86_64)
我有一个13英寸的macbook air(2012)并使用所有Anaconda默认设置,除了:
conda install pandas=0.14.1
编辑添加:以下是一些更新的基准测试。我现在正在使用更快的计算机,所以这将在macbook pro上比较0.16.2和0.17.0(15英寸,2015年中)。
版本0.16.2
%timeit pd.Series(np.repeat(grp.mean().values, grp.count().values))
100 loops, best of 3: 2.71 ms per loop
%timeit grp.transform(np.mean)
100 loops, best of 3: 18.9 ms per loop
版本0.17.0
%timeit pd.Series(np.repeat(grp.mean().values, grp.count().values))
100 loops, best of 3: 2.05 ms per loop
%timeit grp.transform(np.mean)
1000 loops, best of 3: 1.45 ms per loop
答案 0 :(得分:3)
这个PR中的0.14.1中的性能提升没有涉及直接(或通过名称)传递的cythonized函数的情况,而是改进了泛型函数的性能(例如,通过了lambda),通过优化结果的设置方式。这个PR解决(并使用)上述解决方案,以在使用cythonized(内部)功能时提供实质性的性能提升,例如:在这种情况下'意味着'。
在测试示例中从3.6s到100ms。请注意,这不如上面的示例那么好,因为您有一个隐式优化。即,群组排序是单调增加的。例如。你的小组按照相同的顺序,而不是相互穿插。
Pandas会处理这两种情况,但检查这个指数实际上是单调的需要花费很少的时间(因此差异)。
这是合并到master / 0.15.0(发布9月底的概要),虽然你可以简单地从master克隆,并且经常发布windows二进制文件。