简体   繁体   English

Xarray加权平均滚动

[英]Xarray rolling mean with weights

When I do running / rolling mean with weights in numpy, I eg do something like this: 当我使用numpy中的权重进行运行/滚动均值时,我会执行以下操作:

data = np.random.random(100)  # Example data...
weights = np.array([1, 2, 1])
data_m = np.convolve(data, weights/float(np.sum(weights)), "same")

And then replace data_m[0] and data_m[-1] with eg nans, depending on application. 然后根据应用将data_m [0]和data_m [-1]替换为nans。

Something alike can be done with xarray. xarray可以完成类似的操作。 What I do (in this case) is 我所做的(在这种情况下)是

xr.DataArray(data).rolling(dim_0=3, center=True).mean(dim="dim_0")

But this corresponds to the weights 但这对应于权重

weights = np.array([1, 1, 1])

in the numpy example. 在numpy示例中。 How would I apply other weights, when using xarray? 使用xarray时,我将如何应用其他权重?

The weighted-rolling-mean is not yet implemented in xarray. 加权滚动平均值尚未在xarray中实现。

The following does almost the same thing but it would be quite slow. 下面的代码几乎做同样的事情,但是会很慢。 I think the use of np.convolve is the current best choice. 我认为使用np.convolve是当前的最佳选择。

def weighted_sum(x, axis):
    weight = [1, 2, 1]
    if x.shape[axis] == 3:
        return np.sum(x * weight, axis=axis)
    else:
        return np.nan

da.rolling(dim_0=3, center=True).reduce(weighted_sum)

Currently, we are working to support more flexible (and faster) rolling operations. 当前,我们正在努力支持更灵活(和更快)的滚动操作。 See https://github.com/pydata/xarray/pull/1837 参见https://github.com/pydata/xarray/pull/1837

EDIT: 编辑:

With xarray=0.10.2, weighted rolling mean can be computed as follows, 使用xarray = 0.10.2时,加权滚动平均值可以如下计算:

weight = xr.DataArray([0.25, 0.5, 0.25], dims=['window'])
da.rolling(dim_0=3, center=True).construct('window').dot(weight)

where construct method constructs a view of the rolling object, where the window dimension (named window in the above example) is attatched to the last position. where construct方法构造滚动对象的视图,其中窗口尺寸(在上面的示例中为window )附加到最后一个位置。 inner product with the weight array gives the weighted sum along the window dimension. 权重数组的内部乘积给出沿窗口维度的加权和。

If you want a Gaussian -like filter, another hack is to apply the rolling mean recursively. 如果您想要类似Gaussian的滤波器,另一个技巧是递归地应用滚动平均值。

Infinite recursions of the boxcar filter (ie, our rolling mean) becomes a Gaussian filter. 箱式滤波器的无限递归(即我们的滚动平均值)成为高斯滤波器。 See B-spline in wikipedia for the detail. 有关详细信息,请参见Wikipedia中的B样条

Example: 例:

x = xr.DataArray([0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], dims=['x'])

# With window=2
tmp = x
plt.plot(tmp, '-ok', label='original')
for i in range(3):
    tmp = tmp.rolling(x=2, min_periods=1).mean()
    plt.plot(tmp, '-o', label='{}-times'.format(i+1))
plt.legend()

窗口大小为2的递归滚动均值

# with window=3, center=True
tmp = x
plt.plot(tmp, '--ok', label='original')
for i in range(3):
    tmp = tmp.rolling(x=3, center=True, min_periods=1).mean()
    plt.plot(tmp, '-o', label='{}-times'.format(i+1))
plt.legend()

集中化窗口大小为3的递归滚动均值

Note: if you want to centralize the result, use the odd window size. 注意:如果要集中结果,请使用奇数窗口大小。

This is specific for the [1,2,1] weights, and it requires two steps, so it is not the best solution, but it is quite quick: 这是特定于[1,2,1]权重的,它需要两个步骤,因此它不是最佳的解决方案,但是速度很快:

dim_name = "dim_0"
da_mean = da.rolling(**{dim_name: 3, "center": True}).mean(dim=dim_name)
da_mean = (3 * da_mean + da) / 4.  # Expand it, and add the middle value.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM