升级后Pandas系列操作非常慢

时间:2014-06-04 03:02:33

标签: python pandas

我发现简单系列操作中pandas 0.11和pandas 0.13之间的性能差异很大。

In [7]: df = pandas.DataFrame({'a':np.arange(1000000), 'b':np.arange(1000000)})

In [8]: pandas.__version__                                
Out[8]: '0.13.0'

In [9]: %timeit df['a'].values+df['b'].values
100 loops, best of 3: 4.33 ms per loop

In [10]: %timeit df['a']+df['b']                      
10 loops, best of 3: 42.5 ms per loop

在版本0.11上(在同一台机器上),

In [10]: pandas.__version__                               
Out[10]: '0.11.0'

In [11]: df = pandas.DataFrame({'a':np.arange(1000000), 'b':np.arange(1000000)})

In [12]: %timeit df['a'].values+df['b'].valuese
100 loops, best of 3: 2.22 ms per loop

In [13]: %timeit df['a']+df['b']     
100 loops, best of 3: 2.3 ms per loop

所以在0.13上,它的速度要慢20倍。剖析它,我看到了

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.047    0.047 <string>:1(<module>)
        1    0.000    0.000    0.047    0.047 ops.py:462(wrapper)
        3    0.000    0.000    0.044    0.015 series.py:134(__init__)
        1    0.000    0.000    0.044    0.044 series.py:2394(_sanitize_array)
        1    0.000    0.000    0.044    0.044 series.py:2407(_try_cast)
        1    0.000    0.000    0.044    0.044 common.py:1708(_possibly_cast_to_datetime)
        1    0.044    0.044    0.044    0.044 {pandas.lib.infer_dtype}
        1    0.000    0.000    0.003    0.003 ops.py:442(na_op)
        1    0.000    0.000    0.003    0.003 expressions.py:193(evaluate)
        1    0.000    0.000    0.003    0.003 expressions.py:93(_evaluate_numexpr)

所以它花了很多时间在_possibly_cash_to_datetime和pandas.lib.infer_dtype上。

预计会有这种变化吗?如何才能恢复旧的,更快的性能?

注意:问题是输出是整数类型。如果我把其中一个列加倍,那就会变得很快......

1 个答案:

答案 0 :(得分:2)

这是一个非常奇怪的错误(我想),在cython中进行奇怪的查找。出于某种原因

_TYPE_MAP = { np.int64 : 'integer' }
np.int64 in _TYPE_MAP

没有正确评估,仅适用于int64(但对所有其他dtypes工作得很好)。由于某些原因,np.dtype对象的哈希值可能很复杂。在任何情况下,修复此处:https:github.com/pydata/pandas/pull/7342所以我们使用名称哈希代替。

这里是性能比较:

In [1]: df = pandas.DataFrame({'a':np.arange(1000000), 'b':np.arange(1000000)})

In [2]: %timeit df['a'] + df['b']
100 loops, best of 3: 2.49 ms per loop

0.14.0

In [6]: df = pandas.DataFrame({'a':np.arange(1000000), 'b':np.arange(1000000)})

In [7]: %timeit df['a'] + df['b']
10 loops, best of 3: 35.1 ms per loop