numpy数组区域统计

Statistics of region of numpy array

我有一个大约有 2000 个元素长的数组,我想通过在它上面滑动一个宽度相对较小的假想 window 来计算它以每个像素为中心的标准偏差,并计算每个区域中元素的 StDev,生成一个与输入元素数量相同的数组。因此,如果宽度设置为 5,则以元素零为中心的 StDev 将计算 np.std(arr[0:3]).

更具体地说,假设您的输入数组是

[0.14  0.1  0.12  0.25  0.29  0.17  0.21  0.22  0.16  0.18  0.14]

并且您希望宽度为 7。对于元素 0,您将计算 stdev([0.14 0.1 0.12 0.25]),对于元素 2,您将计算 stdev([0.14 0.1 0.12 0.25 0.29]),依此类推。

似乎一个天真的解决方案是遍历输入数组并通过 floor(width/2) 个元素扩展输入数组(简单地屏蔽掉第一个和最后几个像素的外部元素),或者只是修改使用的宽度。

有没有更快的方法,尤其是不需要重复选择子数组的方法?

您可以使用 stride_tricks 在数组上创建一个非常节省内存的视图,但这仍然不能解决您在边缘 window 的问题,其中 window 是"cut-off" 或减少。在那里,您可以考虑迭代不同的 window 大小。如果 window 大小比您要计算标准偏差(或相关平均值)的数组小得多,它会给您带来速度提升。

import numpy as np
from numpy.lib.stride_tricks import as_strided

a = np.arange(20)
windowlen = 5
assert windowlen & 1  # this method only works for windows of uneven size
b = np.empty(a.shape)
b[windowlen//2:a.size - windowlen//2] = as_strided(a,
    shape=(a.size - windowlen + 1, windowlen),
    strides=a.strides*2).std(axis=-1)

for ind in range(windowlen//2):  # iterate over the edges where the windowsize is reduced
    lim = windowlen//2 + 1 + ind
    b[ind] = a[:lim].std()
    b[-1 - ind] = a[-lim:].std()

# b: array([ 0.81649658,  1.11803399,  1.41421356,  1.41421356,  1.41421356,
#    1.41421356,  1.41421356,  1.41421356,  1.41421356,  1.41421356,
#    1.41421356,  1.41421356,  1.41421356,  1.41421356,  1.41421356,
#    1.41421356,  1.41421356,  1.41421356,  1.11803399,  0.81649658])

如您所见,我添加了一个断言,因为这个想法只有在 window 的长度为奇数时才能正常工作。否则,您希望数组的 std 在哪里,例如四个元素 - 在索引为 1 的元素或索引为 2 的元素?

您可以使用 pandas 轻松完成此操作。

import pandas as pd

data = np.random.random(20)
stds = pd.rolling_std(data, window=7, center=True, min_periods=1)  # min_periods to get the edges