我发现 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 上花费了大量时间。
这种变化是预期的吗?我怎样才能恢复原来更快的性能?
注意:看来问题是输出的是整数类型。如果我将其中一列加倍,它会变快...
最佳答案
这是一个非常奇怪的错误,必须(我认为)在 cython 中进行奇怪的查找。出于某种原因
_TYPE_MAP = { np.int64 : 'integer' }
np.int64 in _TYPE_MAP
没有正确评估,仅适用于 int64
(但适用于所有其他数据类型)。由于某种原因,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
关于python - 升级后 Pandas 系列操作非常缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24028281/