【问题标题】:Xarray rolling mean with weightsXarray 滚动平均值与权重
【发布时间】:2018-07-08 17:03:26
【问题描述】:

当我在 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")

然后将 data_m[0] 和 data_m[-1] 替换为例如nans,取决于应用程序。

类似的事情可以用 xarray 来完成。我所做的(在这种情况下)是

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

但这对应于权重

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

在 numpy 示例中。使用 xarray 时如何应用其他权重?

【问题讨论】:

    标签: python numpy python-xarray xarray


    【解决方案1】:

    加权滚动均值尚未在 xarray 中实现。

    以下内容几乎相同,但速度会很慢。 我认为使用 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)
    

    目前,我们正在努力支持更灵活(更快)的滚动操作。见https://github.com/pydata/xarray/pull/1837

    编辑:

    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)
    

    其中construct 方法构造了滚动对象的视图,其中窗口尺寸(上例中名为window)附加到最后一个位置。 与权重数组的内积给出沿窗口维度的加权和。

    【讨论】:

    • 不确定,但我认为您需要除以权重之和,对吧? da.rolling(dim_0=3, center=True).construct('window').dot(weight)/weight.sum()
    【解决方案2】:

    如果你想要一个类似Gaussian 的过滤器,另一个技巧是递归地应用滚动平均值。

    boxcar 滤波器(即我们的滚动平均值)的无限递归变为高斯滤波器。 详情请见B-spline in wikipedia

    例子:

    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()
    

    # 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】:

      这是针对 [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.
      

      【讨论】:

        猜你喜欢
        • 2018-02-10
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        • 2021-12-18
        • 2018-04-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多