title: Apply rolling function to groupby over several columns
body: <p>I'd like to apply rolling functions to a dataframe grouped by two columns with repeated date entries. Specifically, with both "freq" and "window" as datetime values, not simply ints.</p>
  
  <p>In principle, I'm try to combine the methods from <a href="https://stackoverflow.com/questions/28642511/how-to-apply-rolling-functions-in-a-group-by-object-in-pandas">How to apply rolling functions in a group by object in pandas</a> and <a href="https://stackoverflow.com/questions/27062652/pandas-rolling-sum-of-last-five-minutes">pandas rolling sum of last five minutes</a>.</p>
  
  <p><strong>Input</strong></p>
  
  <p>Here is a sample of the data, with one id=33 although we expect several id's.</p>
  
  <pre><code>X = [{'date': '2017-02-05', 'id': 33, 'item': 'A', 'points': 20},
   {'date': '2017-02-05', 'id': 33, 'item': 'B', 'points': 10},
   {'date': '2017-02-06', 'id': 33, 'item': 'B', 'points': 10},
   {'date': '2017-02-11', 'id': 33, 'item': 'A', 'points': 1},
   {'date': '2017-02-11', 'id': 33, 'item': 'A', 'points': 1},
   {'date': '2017-02-11', 'id': 33, 'item': 'A', 'points': 1},
   {'date': '2017-02-13', 'id': 33, 'item': 'A', 'points': 4}]
  
  # df = pd.DataFrame(X) and reindex df to pd.to_datetime(df['date'])
  
  df
  
              id item  points
  date                       
  2017-02-05  33    A      20
  2017-02-05  33    B      10
  2017-02-06  33    B      10
  2017-02-11  33    A       1
  2017-02-11  33    A       1
  2017-02-11  33    A       1
  2017-02-13  33    A       4
  </code></pre>
  
  <p><strong>Goal</strong></p>
  
  <p>Sample each 'id' every 2 days (freq='2d') and return the sum of total points for each item over the previous three days (window='3D'), end-date inclusive</p>
  
  <p><strong>Desired Output</strong></p>
  
  <pre><code>            id    A    B
  date                       
  2017-02-05  33    20   10
  2017-02-07  33    20   30    
  2017-02-09  33    0    10
  2017-02-11  33    3    0
  2017-02-13  33    7    0
  </code></pre>
  
  <p>E.g. on the right-inclusive end-date 2017-02-13, we sample the 3-day period 2017-02-11 to 2017-02-13. In this period, id=33 had a sum of A points equal to 1+1+1+4 = 7</p>
  
  <p><strong>Attempts</strong></p>
  
  <p>An attempt of groupby with a pd.rolling_sum as follows didn't work, due to repeated dates</p>
  
  <pre><code>df.groupby(['id', 'item'])['points'].apply(pd.rolling_sum, freq='4D', window=3)
  ValueError: cannot reindex from a duplicate axis
  </code></pre>
  
  <p>Also note that from the documentation <a href="http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.rolling_apply.html" rel="nofollow noreferrer">http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.rolling_apply.html</a> 'window' is an int representing the size sample period, not the number of days to sample.</p>
  
  <p>We can also try resampling and using last, however the desired look-back of 3 days doesn't seem to be used</p>
  
  <pre><code>df.groupby(['id', 'item'])['points'].resample('2D', label='right', closed='right').\
  apply(lambda x: x.last('3D').sum())
  
  id  item  date      
  33  A     2017-02-05    20
            2017-02-07     0
            2017-02-09     0
            2017-02-11     3
            2017-02-13     4
      B     2017-02-05    10
            2017-02-07    10
  </code></pre>
  
  <p>Of course,setting up a loop over unique id's ID, selecting df_id = df[df['id']==ID], and summing over the periods does work but is computationally-intensive and doesn't exploit groupby's nice vectorization.</p>
  
  <p>Thanks to @jezrael for good suggestions so far</p>
  
  <p><strong>Notes</strong></p>
  
  <p>Pandas version = 0.20.1</p>
  
  <p>I'm a little confused as to why the documentation on rolling() here:<a href="https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rolling.html" rel="nofollow noreferrer">https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rolling.html</a>
  suggests that the "window" parameter can be in an int or offset but on attempting df.rolling(window='3D',...) I get<code>raise ValueError("window must be an integer")
  </code>
  It appears that the above documentation is not consistent with the latest code for rolling's window from ./core/window.py :
  <a href="https://github.com/pandas-dev/pandas/blob/master/pandas/core/window.py" rel="nofollow noreferrer">https://github.com/pandas-dev/pandas/blob/master/pandas/core/window.py</a></p>
  
  <pre><code>elif not is_integer(self.window):
              raise ValueError("window must be an integer")
  </code></pre>