title: Weighted moving average in python
body: <p>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 of a moving average, but I am having trouble finding a good way to do a weighted moving average, so that the values towards the center of the bin are weighted more than values towards the edges.</p>
  
  <p>Here I generate some sample data and then take a moving average. How can I most easily implement a weighted moving average? Thanks!</p>
  
  <pre><code>import numpy as np
  import matplotlib.pyplot as plt
  
  #first generate some datapoint for a randomly sampled noisy sinewave
  x = np.random.random(1000)*10
  noise = np.random.normal(scale=0.3,size=len(x))
  y = np.sin(x) + noise
  
  #plot the data
  plt.plot(x,y,'ro',alpha=0.3,ms=4,label='data')
  plt.xlabel('Time')
  plt.ylabel('Intensity')
  
  #define a moving average function
  def moving_average(x,y,step_size=.1,bin_size=1):
      bin_centers  = np.arange(np.min(x),np.max(x)-0.5*step_size,step_size)+0.5*step_size
      bin_avg = np.zeros(len(bin_centers))
  
      for index in range(0,len(bin_centers)):
          bin_center = bin_centers[index]
          items_in_bin = y[(x&gt;(bin_center-bin_size*0.5) ) &amp; (x&lt;(bin_center+bin_size*0.5))]
          bin_avg[index] = np.mean(items_in_bin)
  
      return bin_centers,bin_avg
  
  #plot the moving average
  bins, average = moving_average(x,y)
  plt.plot(bins, average,label='moving average')
  
  plt.show()
  </code></pre>
  
  <p>The output:
  <img src="https://i.stack.imgur.com/ca0kN.png" alt="Data and moving average"></p>
  
  <p>Using the advice from crs17 to use "weights=" in the np.average function, I came up weighted average function, which uses a Gaussian function to weight the data:</p>
  
  <pre><code>def weighted_moving_average(x,y,step_size=0.05,width=1):
      bin_centers  = np.arange(np.min(x),np.max(x)-0.5*step_size,step_size)+0.5*step_size
      bin_avg = np.zeros(len(bin_centers))
  
      #We're going to weight with a Gaussian function
      def gaussian(x,amp=1,mean=0,sigma=1):
          return amp*np.exp(-(x-mean)**2/(2*sigma**2))
  
      for index in range(0,len(bin_centers)):
          bin_center = bin_centers[index]
          weights = gaussian(x,mean=bin_center,sigma=width)
          bin_avg[index] = np.average(y,weights=weights)
  
      return (bin_centers,bin_avg)
  </code></pre>
  
  <p>Results look good:
  <img src="https://i.stack.imgur.com/SV7wj.png" alt="Working weighted average using numpy"></p>