Search code examples
pythonpandasexponentialweightedweighted-average

Applying the Python Pandas Exponential Weighted Average in Reverse Order


For a pandas.DataFrame example:

In: cols = ['cols1', 'cols2']
In: df = pd.DataFrame({'col1': [1, 2, 3, 4], 'col2': [3, 4, 5, 6]})

Out:       col1  col2
      0     1     3
      1     2     4
      2     3     5
      3     4     6

I am using the Exponential Weighted Average:

In: for i in range(len(df.columns)):
       df[cols[i]] = df[cols[i]].ewm(com=None, span=None, halflife=None, 
                                     alpha=.8, min_periods=0, adjust=True,
                                     ignore_na=False, axis=0).mean()

It works great! However the weights are applied with exponentially decreasing values from top down:

  Out:      col1      col2
      0  1.000000  3.000000
      1  1.833333  3.833333
      2  2.774194  4.774194
      3  3.756410  5.756410

I am wondering if there is a way to apply the weights in the reverse order (bottom up). My desired output is:

Out:          col1          col2
      0     0.9391025     2.8173075
      1     1.8494627     3.6982925
      2     2.7499995     4.5833325
      3     4.000000      6.000000

Solution

  • I found a solution to the problem. You can reindex before and after applying ewm():

    In: df.reindex(index=df.index[:-1])
        for i in range(len(df.columns)):
            df[cols[i]] = df[cols[i]].ewm(com=None, span=None, halflife=None, 
                                          alpha=.8, min_periods=0, adjust=True,
                                          ignore_na=False, axis=0).mean()
    Out:        col1      col2
          3  4.000000  6.000000
          2  3.166667  5.166667
          1  2.225806  4.225806
          0  1.243590  3.243590
    

    Then you can apply it again:

    In: df.reindex(index=df.index[:-1])
    Out:        col1      col2
           0  1.243590  3.243590
           1  2.225806  4.225806
           2  3.166667  5.166667
           3  4.000000  6.000000
    

    I am still unsure if this is the most efficient method. So, if anyone has any other ideas, I would love to know.