python - Series 和 Numpy 的性能比较
问题描述
我正在构建 Numpy 和 Series 之间的性能比较表:
两个实例引起了我的注意。任何帮助都会非常有帮助。
- 我们说我们应该避免在 Numpy 和 Series 中使用循环,但我遇到了一种情况,其中 for 循环的性能更好
在下面的代码中,我使用 for 循环和不使用 for 循环来计算行星的密度
mass= pd.Series([0.330, 4.87, 5.97, 0.073, 0.642, 1898, 568, 86.8, 102, 0.0146], index = ['MERCURY', 'VENUS', 'EARTH', 'MOON', 'MARS', 'JUPITER', 'SATURN', 'URANUS', 'NEPTUNE', 'PLUTO'])
diameter = pd.Series([4879, 12104, 12756, 3475, 6792, 142984, 120536, 51118, 49528, 2370], index = ['MERCURY', 'VENUS', 'EARTH', 'MOON', 'MARS', 'JUPITER', 'SATURN', 'URANUS', 'NEPTUNE', 'PLUTO'])
%%timeit -n 1000
density = mass / (np.pi * np.power(diameter, 3) /6)
1000 loops, best of 3: 617 µs per loop
%%timeit -n 1000
density = pd.Series()
for planet in mass.index:
density[planet] = mass[planet] / ((np.pi * np.power(diameter[planet], 3)) / 6)
1000 loops, best of 3: 183 µs per loop
- 其次,我正在尝试使用两种方法替换 Series 中的 nan 值
为什么第一种方法工作得更快???我猜第二种方法是在 Nd 数组中转换 Series Object
sample2 = pd.Series([1, 2, 3, 4325, 23, 3, 4213, 102, 89, 4, np.nan, 6, 803, 43, np.nan, np.nan, np.nan])
x = np.mean(sample2)
x
%%timeit -n 10000
sample3 = pd.Series(np.where(np.isnan(sample2), x, sample2))
10000 loops, best of 3: 166 µs per loop
%%timeit -n 10000
sample2[np.isnan(sample2)] =x
10000 loops, best of 3: 1.08 ms per loop
解决方案
在ipython
控制台会话中:
In [1]: import pandas as pd
In [2]: mass= pd.Series([0.330, 4.87, 5.97, 0.073, 0.642, 1898, 568, 86.8, 102, 0.
...: 0146], index = ['MERCURY', 'VENUS', 'EARTH', 'MOON', 'MARS', 'JUPITER', 'SA
...: TURN', 'URANUS', 'NEPTUNE', 'PLUTO'])
...: diameter = pd.Series([4879, 12104, 12756, 3475, 6792, 142984, 120536, 51118
...: , 49528, 2370], index = ['MERCURY', 'VENUS', 'EARTH', 'MOON', 'MARS', 'JUPI
...: TER', 'SATURN', 'URANUS', 'NEPTUNE', 'PLUTO'])
...:
In [3]: mass
Out[3]:
MERCURY 0.3300
VENUS 4.8700
EARTH 5.9700
MOON 0.0730
MARS 0.6420
JUPITER 1898.0000
SATURN 568.0000
URANUS 86.8000
NEPTUNE 102.0000
PLUTO 0.0146
dtype: float64
In [4]: diameter
Out[4]:
MERCURY 4879
VENUS 12104
EARTH 12756
MOON 3475
MARS 6792
JUPITER 142984
SATURN 120536
URANUS 51118
NEPTUNE 49528
PLUTO 2370
dtype: int64
您的密度计算会创建一个具有相同索引的系列。这里系列的索引匹配,但我认为总的来说pandas
能够匹配索引。
In [5]: density = mass / (np.pi * np.power(diameter, 3) /6)
In [6]: density
Out[6]:
MERCURY 5.426538e-12
VENUS 5.244977e-12
EARTH 5.493286e-12
MOON 3.322460e-12
MARS 3.913302e-12
JUPITER 1.240039e-12
SATURN 6.194402e-13
URANUS 1.241079e-12
NEPTUNE 1.603427e-12
PLUTO 2.094639e-12
dtype: float64
In [7]: timeit density = mass / (np.pi * np.power(diameter, 3) /6)
532 µs ± 437 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
由于索引匹配,我们可以使用numpy
values 数组获得相同的数字:
In [8]: mass.values/(np.pi * np.power(diameter.values, 3)/6)
Out[8]:
array([5.42653818e-12, 5.24497707e-12, 5.49328558e-12, 3.32246038e-12,
3.91330208e-12, 1.24003876e-12, 6.19440202e-13, 1.24107933e-12,
1.60342694e-12, 2.09463905e-12])
In [9]: timeit mass.values/(np.pi * np.power(diameter.values, 3)/6)
11.5 µs ± 67.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
这要快得多。 numpy
没有花时间来匹配索引。它也没有制作新的系列。
您的迭代方法:
In [11]: %%timeit
...: density = pd.Series(dtype=float)
...: for planet in mass.index:
...: density[planet] = mass[planet] / ((np.pi * np.power(diameter[planet],
...: 3)) / 6)
...:
7.36 ms ± 312 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
这要慢得多。
出于好奇,让我们初始化一个系列并用numpy
计算填充它:
In [18]: %%timeit
...: density = pd.Series(index=mass.index, dtype=float)
...: density[:] = mass.values/(np.pi * np.power(diameter.values, 3)/6)
241 µs ± 8.97 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
比 [7] 好 2 倍,但仍然比 pure 慢很多numpy
。虽然pandas
使用numpy
数组 - 在这里我认为两者index
都是values
数组。但是pandas
相对于纯numpy
代码确实增加了显着的开销。
推荐阅读
- android-studio - 切换按钮最初未被选中
- fortran - Pi 计算使用 OpenMP 给出了不正确的结果
- typescript - TS2531:对象可能为“空”。离子 - Vue.js
- python - 如何在 pandas 中按 2 个条件聚合?
- cordova - 如何安装离子科尔多瓦本地通知扩展?
- reactjs - 反应忽略 useMobileDetection 自定义挂钩返回值,除非调整大小
- arrays - 打印在 C 中多次重新分配的数组
- chef-infra - 如何在 Knife.rb 文件中屏蔽输出日志
- firefox - 如何在启用全屏的 iframe 中运行网站。firefox 进入全屏,但如果单击另一个链接 FF 退出
- reactjs - React JS Fluent ui onRenderTitle