2016-09-07 9 views
2

Ich habe sessions Datenrahmen, der E-mail und Sessions (int) Spalten enthält.Rolling Summe in Untergruppen eines Datenrahmens (Pandas)

Ich muss rollende Summe der Sitzungen per E-Mail (d. H. Nicht global) berechnen.

nun die folgenden Werke, aber es ist sehr langsam:

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) 

Gibt es eine Möglichkeit, das gleiche in pandas zu erreichen, aber unter Verwendung von pandas Operatoren auf einem Datenrahmen statt der Schaffung separaten Datenrahmen für jede E-Mail und dann Verketten sie?

(entweder das, oder irgendeine andere Art und Weise dies schneller zu machen)

Antwort

2

Setup-

np.random.seed([3,1415]) 
df = pd.DataFrame({'E-Mail': np.random.choice(list('AB'), 20), 
        'Session': np.random.randint(1, 10, 20)}) 

Lösung

die aktuelle und richtige Weg, dies zu tun ist mit rolling.sum, die auf dem Ergebnis einer pd.Series Gruppe von Objekt verwendet B.

#  Series Group By 
# /------------------------\ 
df.groupby('E-Mail').Session.rolling(3).sum() 
#       \--------------/ 
#        Method you want 

E-Mail  
A  0  NaN 
     2  NaN 
     4  11.0 
     5  7.0 
     7  10.0 
     12 16.0 
     15 16.0 
     17 16.0 
     18 17.0 
     19 18.0 
B  1  NaN 
     3  NaN 
     6  18.0 
     8  14.0 
     9  16.0 
     10 12.0 
     11 13.0 
     13 16.0 
     14 20.0 
     16 22.0 
Name: Session, dtype: float64 

Einzelheiten

df 

    E-Mail Session 
0  A  9 
1  B  7 
2  A  1 
3  B  3 
4  A  1 
5  A  5 
6  B  8 
7  A  4 
8  B  3 
9  B  5 
10  B  4 
11  B  4 
12  A  7 
13  B  8 
14  B  8 
15  A  5 
16  B  6 
17  A  4 
18  A  8 
19  A  6 
+0

Wie funktioniert 0 + 2 + 4 = 11? – Blake

+2

@Blake Ich weiß es nicht. Wie? Wenn Sie sich auf die Indexwerte beziehen, schauen Sie sich an, wo die ersten 3 Werte von "E-Mail" gleich "A" sind. Sie werden sehen, dass die Indexwerte "0", "2" und "4" sind. Diese Indexwerte werden in die zweite Ebene eines Pandas 'MultiIndex' eingebettet. '11' ist das Ergebnis von' 9 + 1 + 1'. – piRSquared

+0

Ja, ich war verwirrt, was .rolling() tut. Ich dachte, es wäre .cumsum(), aber es ist nur eine gefensterte Aggregation. Ich sehe jetzt – Blake

3

Sagen Sie bitte mit

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 

beginnen übrigens anmerken, dass ich neu geordnet nur Ihre rolling_sum, aber es veraltet ist - Sie sollten jetzt verwenden rolling:

df[['Session']].groupby(df['E-Mail']).apply(lambda g: g.rolling(3).sum()) 
+0

in Ordnung, aber was ist der Punkt, den ersten beiden NaN zu machen? Warum haben Sie nicht die rollende Summe für Bar-Print 3, 7, 12 und foo Druck 0,1,3, etc.? – Blake

Verwandte Themen