Rolling sum in subgroups of a dataframe (pandas)
<p>I have <code>sessions</code> dataframe that contains <code>E-mail</code> and <code>Sessions</code> (int) columns. </p>

<p>I need to calculate rolling sum of sessions <em>per email</em> (i.e. not globally).</p>

<p>Now, the following works, but it's painfully slow:</p>

<pre><code>emails = set(list(sessions['E-mail']))
ses_sums = []
for em in emails:
    email_sessions = sessions[sessions['E-mail'] == em]
    email_sessions.is_copy = False
    email_sessions['Session_Rolling_Sum'] = pd.rolling_sum(email_sessions['Sessions'], window=self.window).fillna(0)
    ses_sums.append(email_sessions)
df = pd.concat(ses_sums, ignore_index=True)
</code></pre>

<p>Is there a way of achieving the same in <code>pandas</code>, but using <code>pandas</code> operators on a dataframe instead of creating separate dataframes for each email and then concatenating them?</p>

<p>(either that or some other way of making this faster)</p>

<p>Say you start with</p>

<pre><code>In [58]: df = pd.DataFrame({'E-Mail': ['foo'] * 3 + ['bar'] * 3 + ['foo'] * 3, 'Session': range(9)})

In [59]: df
Out[59]: 
  E-Mail  Session
0    foo        0
1    foo        1
2    foo        2
3    bar        3
4    bar        4
5    bar        5
6    foo        6
7    foo        7
8    foo        8

In [60]: df[['Session']].groupby(df['E-Mail']).apply(pd.rolling_sum, 3)
Out[60]: 
          Session
E-Mail           
bar    3      NaN
       4      NaN
       5     12.0
foo    0      NaN
       1      NaN
       2      3.0
       6      9.0
       7     15.0
       8     21.0
</code></pre>

<p>Incidentally, note that I just rearranged your <code>rolling_sum</code>, but it has been deprecated - you should now use <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rolling.html" rel="nofollow"><code>rolling</code></a>:</p>

<pre><code>df[['Session']].groupby(df['E-Mail']).apply(lambda g: g.rolling(3).sum())
</code></pre>

python performance pandas