为什么statistics.mean()
与NumPy版本相比,甚至与一个简单的实现(例如:
def mean(items):
return sum(items) / len(items)
在我的系统中,我得到以下计时:
import numpy as np
import statistics
ll_int = [x for x in range(100_000)]
%timeit statistics.mean(ll_int)
# 42 ms ± 408 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit sum(ll_int) / len(ll_int)
# 460 µs ± 5.43 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.mean(ll_int)
# 4.62 ms ± 38.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
ll_float = [x / 10 for x in range(100_000)]
%timeit statistics.mean(ll_float)
# 56.7 ms ± 879 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit sum(ll_float) / len(ll_float)
# 459 µs ± 7.39 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.mean(ll_float)
# 2.7 ms ± 11.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
对于其他函数,如variance
或stdev
,我得到了类似的计时。你知道吗
编辑: 即使是这样的迭代实现:
def next_mean(value, mean_, num):
return (num * mean_ + value) / (num + 1)
def imean(items, mean_=0.0):
for i, item in enumerate(items):
mean_ = next_mean(item, mean_, i)
return mean_
似乎更快:
%timeit imean(ll_int)
# 16.6 ms ± 62.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit imean(ll_float)
# 16.2 ms ± 429 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
statistics module使用解释的Python代码,但是
numpy
使用优化的编译代码来完成所有繁重的工作,因此如果numpy
没有将statistics
从水中吹出来,那将是令人惊讶的。你知道吗此外,statistics被设计成与decimal和fractions这样的模块配合使用,并且使用了重视数值精度和类型安全性的代码。您的天真实现使用
sum
。统计模块在内部使用自己的函数_sum
。Looking at its source表明它所做的远远不止是把东西加在一起:这段代码最令人惊讶的地方是它将数据转换成分数,以最小化舍入误差。没有理由期望这样的代码会像简单的
sum(nums)/len(nums)
方法那样快速。你知道吗统计模块的开发人员用explicit decision来评估正确性而不是速度:
而且stated我们无意
但是,提出了一个enhancement request来添加一个额外的、更快、更简单的实现statistics.fmean,这个函数将在python3.8中发布。根据增强开发者的说法,这个函数比现有的
statistics.mean
快500倍。你知道吗fmean
implementation基本上是sum/len
。你知道吗相关问题 更多 >
编程相关推荐