Weighted moving average in python

前端 未结 2 1065
有刺的猬
有刺的猬 2020-12-08 08:03

I have data sampled at essentially random intervals. I would like to compute a weighted moving average using numpy (or other python package). I have a crude implementation o

2条回答
  •  借酒劲吻你
    2020-12-08 08:46

    This won't give an exact solution, but it will make your life easier, and will probably be good enough... First, average your samples in small bins. Once you have resampled your data to be equispaced, you can use stride tricks and np.average to do a weighted average:

    from numpy.lib.stride_tricks import as_strided
    
    def moving_weighted_average(x, y, step_size=.1, steps_per_bin=10,
                                weights=None):
        # This ensures that all samples are within a bin
        number_of_bins = int(np.ceil(np.ptp(x) / step_size))
        bins = np.linspace(np.min(x), np.min(x) + step_size*number_of_bins,
                           num=number_of_bins+1)
        bins -= (bins[-1] - np.max(x)) / 2
        bin_centers = bins[:-steps_per_bin] + step_size*steps_per_bin/2
    
        counts, _ = np.histogram(x, bins=bins)
        vals, _ = np.histogram(x, bins=bins, weights=y)
        bin_avgs = vals / counts
        n = len(bin_avgs)
        windowed_bin_avgs = as_strided(bin_avgs,
                                       (n-steps_per_bin+1, steps_per_bin),
                                       bin_avgs.strides*2)
    
        weighted_average = np.average(windowed_bin_avgs, axis=1, weights=weights)
    
        return bin_centers, weighted_average
    

    You can now do something like this:

    #plot the moving average with triangular weights
    weights = np.concatenate((np.arange(0, 5), np.arange(0, 5)[::-1]))
    bins, average = moving_weighted_average(x, y, steps_per_bin=len(weights),
                                            weights=weights)
    plt.plot(bins, average,label='moving average')
    
    plt.show()
    

    enter image description here

提交回复
热议问题