Weighted moving average in python

前端 未结 2 1058
有刺的猬
有刺的猬 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

    0 讨论(0)
  • 2020-12-08 09:05

    You could use numpy.average which allows you to specify weights:

    >>> bin_avg[index] = np.average(items_in_bin, weights=my_weights)
    

    So to calculate the weights you could find the x coordinates of each data point in the bin and calculate their distances to the bin center.

    0 讨论(0)
提交回复
热议问题