bootstrap 数字列表的平均值的最有效方法是什么?

What is the most efficient way to bootstrap the mean of a list of numbers?

我有一个数字列表(浮点数),我想估计平均值。我还需要估计这种均值的变化。我的目标是对列表重采样 100 次,我的输出将是一个长度为 100 的数组,每个元素对应于重采样列表的平均值。

这是一个简单可行的示例,说明我想要实现的目标:

import numpy as np
data = np.linspace(0, 4, 5)
ndata, boot = len(data), 100
output = np.mean(np.array([data[k] for k in np.random.uniform(high=ndata, size=boot*ndata).astype(int)]).reshape((boot, ndata)), axis=1)

然而,当我必须对包含大量元素的许多列表重复时,这会非常慢。该方法似乎也非常笨重且非 Pythonic。实现我的目标的更好方法是什么?

P.S。我知道 scipy.stats.bootstrap,但我在 anaconda 中将 scipy 升级到 1.7.1 以导入它时遇到问题。

使用np.random.choice:

import numpy as np

data = np.linspace(0, 4, 5)
ndata, boot = len(data), 100
output = np.mean(
    np.random.choice(data, size=(100, ndata)),
    axis=1)

如果我没理解错的话,这个表达式(在你问题的代码中):

np.array([data[k] for k in np.random.uniform(high=ndata, size=boot*ndata).astype(int)]).reshape((boot, ndata)

正在做有放回的抽样,这正是 np.random.choice 所做的。

以下是一些时间参考:

%timeit np.mean(np.array([data[k] for k in np.random.uniform(high=ndata, size=boot*ndata).astype(int)]).reshape((boot, ndata)), axis=1)
133 µs ± 3.96 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit np.mean(np.random.choice(data, size=(boot, ndata)),axis=1)
41.1 µs ± 538 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

可以看出 np.random.choice 产生了 3 倍的改进。