2013-03-06 17 views
12

Właśnie dokonałem przełączenia z R do Pythona i miałem problemy z przyzwyczajeniem się do ramek danych ponownie, w przeciwieństwie do używania R's data.table. Problemem, który miałem, jest to, że chciałbym wziąć listę ciągów, sprawdzić wartość, a następnie zsumować liczbę tych łańcuchów - z podziałem na użytkownika. Więc chciałbym wziąć te dane:sumy warunkowe dla agregatów pand

A_id  B C 
1: a1 "up" 100 
2: a2 "down" 102 
3: a3 "up" 100 
3: a3 "up" 250 
4: a4 "left" 100 
5: a5 "right" 102 

i powrót:

A_id_grouped sum_up sum_down ... over_200_up 
1:   a1  1   0 ...   0 
2:   a2  0   1     0 
3:   a3  2   0 ...   1 
4:   a4  0   0     0 
5:   a5  0   0 ...   0 

Zanim zrobiłem to z kodu R (używając data.table)

>DT[ ,list(A_id_grouped, sum_up = sum(B == "up"), 
+ sum_down = sum(B == "down"), 
+ ..., 
+ over_200_up = sum(up == "up" & < 200), by=list(A)]; 

Jednak wszystko moje ostatnie próby z Pythonem mnie zawiodły:

DT.agg({"D": [np.sum(DT[DT["B"]=="up"]),np.sum(DT[DT["B"]=="up"])], ... 
    "C": np.sum(DT[(DT["B"]=="up") & (DT["C"]>200)]) 
    }) 

Z góry dziękuję! wydaje się, że to proste pytanie, ale nigdzie nie mogłem go znaleźć.

Odpowiedz

14

celu uzupełnienia odpowiedź unutbu, oto jest podejście z wykorzystaniem apply na obiekcie GroupBy.

>>> df.groupby('A_id').apply(lambda x: pd.Series(dict(
    sum_up=(x.B == 'up').sum(), 
    sum_down=(x.B == 'down').sum(), 
    over_200_up=((x.B == 'up') & (x.C > 200)).sum() 
))) 
     over_200_up sum_down sum_up 
A_id        
a1    0   0  1 
a2    0   1  0 
a3    1   0  2 
a4    0   0  0 
a5    0   0  0 
6

Może istnieć lepszy sposób; Jestem całkiem nowy, pand, ale to działa:

import pandas as pd 
import numpy as np 

df = pd.DataFrame({'A_id':'a1 a2 a3 a3 a4 a5'.split(), 
        'B': 'up down up up left right'.split(), 
        'C': [100, 102, 100, 250, 100, 102]}) 

df['D'] = (df['B']=='up') & (df['C'] > 200) 
grouped = df.groupby(['A_id']) 

def sum_up(grp): 
    return np.sum(grp=='up') 
def sum_down(grp): 
    return np.sum(grp=='down') 
def over_200_up(grp): 
    return np.sum(grp) 

result = grouped.agg({'B': [sum_up, sum_down], 
         'D': [over_200_up]}) 
result.columns = [col[1] for col in result.columns] 
print(result) 

daje

 sum_up sum_down over_200_up 
A_id        
a1   1   0   0 
a2   0   1   0 
a3   2   0   1 
a4   0   0   0 
a5   0   0   0