2013-08-25 2 views
2

У меня есть такая же рамка данных pandas.вычисление текущих итогов в отдельных столбцах в Pandas DF

frame = pd.DataFrame({'home' : ['CHI', 'ATL', 'SEA', 'DET', 'STL','HOU' ,'CHI','CHI'], 
        'away' : ['DET', 'CHI', 'HOU', 'TOR', 'DAL', 'STL', 'MIA', 'SEA']}) 

Благодаря unutbu я могу держать нарастающий итог от общего количества сыгранных игр для каждой команды, как это.

awayGP = collections.Counter() 
homeGP = collections.Counter() 

def count_games(): 
    for idx, row in frame.iterrows(): 
     homeGP[row['home']] +=1 
     awayGP[row['away']] +=1 
     test = homeGP + awayGP 
     yield awayGP[row['away']], awayGP[row['home']], , homeGP[row['away']], homeGP[row['home']] 

frame['awayteamAwayGP'] , frame['hometeamAwayGP'], frame['awayteamHomeGP'],   frame['hometeamHomeGP'] = zip(*list(count_games()))                
frame['awayteamGames'] = frame['awayteamAwayGP'] + frame['awayteamHomeGP']                      
frame['hometeamGames'] = frame['hometeamAwayGP'] + frame['hometeamHomeGP']   
del frame['awayteamAwayGP'] , frame['hometeamAwayGP'], frame['awayteamHomeGP'], frame['hometeamHomeGP'] 

Я хотел был бы быть в состоянии поддерживать общее количество баллов, набранных для каждой команды.

frame['awayPTS'] = [88, 75, 105, 99, 110, 85, 95, 100] 
frame['homePTS'] = [92, 88, 95, 97, 100, 74, 98, 110] 

Это желаемый результат.

away home awayteamGP hometeamGP awayPTS homePTS awayteam_totalPTS hometeam_totalPTS 
DET CHI  1    1  88  92   88    92 
CHI ATL  2    1  75  88   180    88 
HOU SEA  1    1  105  95   105    95 
TOR DET  1    2  99  97   99    187 
DAL STL  1    1  110  100   110    100 
STL HOU  2    2  85  74   185    179 
MIA CHI  1    3  95  98   95    265 
SEA CHI  2    4  100  110   195    375 
+0

Похоже, что должен быть аккуратный способ использования стека (по сути, разделение на прочь/на дом, позволяющее применять группу). –

ответ

3

Создать defualtdict (со значением по умолчанию 0), где вы будете держать текущие десятки команд, и применять по axis=1 функцию, которая обновляет этот словарь и возвращает кортеж результатов. Затем просто соедините свой DataFrame и полученный DataFrame с функцией apply по адресу axis=1.

frame = pd.DataFrame({ 
    'home' : ['CHI', 'ATL', 'SEA', 'DET', 'STL','HOU' ,'CHI','CHI'], 
    'away' : ['DET', 'CHI', 'HOU', 'TOR', 'DAL', 'STL', 'MIA', 'SEA'], 
    'awayPTS' : [88, 75, 105, 99, 110, 85, 95, 100], 
    'homePTS' : [92, 88, 95, 97, 100, 74, 98, 110], 
}) 

score = collections.defaultdict(int) 
def calculate(row): 
    away = row['away'] 
    home = row['home'] 
    score[away] += row['awayPTS'] 
    score[home] += row['homePTS'] 
    return pd.Series([score[away], score[home]], 
        index=['awayteam_totalPTS', 'hometeam_totalPTS']) 
frame = pd.concat([frame, frame.apply(calculate, axis=1)], axis=1) 

Дает:

away home awayPTS homePTS awayteam_totalPTS hometeam_totalPTS 
0 DET CHI  88  92     88     92 
1 CHI ATL  75  88    167     88 
2 HOU SEA  105  95    105     95 
3 TOR DET  99  97     99    185 
4 DAL STL  110  100    110    100 
5 STL HOU  85  74    185    179 
6 MIA CHI  95  98     95    265 
7 SEA CHI  100  110    195    375 
+0

Счетчик FYI - это в основном сахар для defaultdict (int) –

+0

@ AndyHayden Я знаю, я просто привык к 'defaultdict', так как он примерно в 4 раза быстрее. –

+0

stack/groupby/apply * значительно * быстрее, чем этот метод (если есть более 40 строк)! –

3

Я думаю, что это имеет смысл, чтобы сделать groupbycumsum, а затем каждую группу. Стоит отметить, что этот метод будет значительно быстрее, чем решение Counter/defaultdict, когда у вас больше элементов в таблице (я вижу его в два раза быстрее на 100 строк и в пятьдесят раз быстрее с 10000 строк).

Сначала мы должны stack таким образом, мы можем сделать это самостоятельно (в сторону/дома):

In [10]: frame.columns = [['away', 'away', 'home', 'home'], 
          ['team', 'PTS', 'team', 'PTS']] 

In [11]: frame # with nice descriptive column labels 
Out[11]: 
    away away home home 
    team PTS team PTS 
0 DET 88 CHI 92 
1 CHI 75 ATL 88 
2 HOU 105 SEA 95 
3 TOR 99 DET 97 
4 DAL 110 STL 100 
5 STL 85 HOU 74 
6 MIA 95 CHI 98 
7 SEA 100 CHI 110 

In [12]: frame_stacked = frame.stack(0) 

In [13]: frame_stacked 
Out[13]: 
     PTS team 
0 away 88 DET 
    home 92 CHI 
1 away 75 CHI 
    home 88 ATL 
2 away 105 HOU 
    home 95 SEA 
3 away 99 TOR 
    home 97 DET 
4 away 110 DAL 
    home 100 STL 
5 away 85 STL 
    home 74 HOU 
6 away 95 MIA 
    home 98 CHI 
7 away 100 SEA 
    home 110 CHI 

Теперь мы можем GroupBy команду здесь (и cumsum будет включать в себя как их прочь и домашние игры):

In [14]: total_pts = frame_stacked.groupby('team')['PTS'].cumsum() 

In [15]: total_pts 
Out[15]: 
0 away  88 
    home  92 
1 away 167 
    home  88 
2 away 105 
    home  95 
3 away  99 
    home 185 
4 away 110 
    home 100 
5 away 185 
    home 179 
6 away  95 
    home 265 
7 away 195 
    home 375 
dtype: int64 

Наконец, мы просто должны вставить их в рамку с правильно именованными столбцами:

In [16]: frame[('home', 'totalPTS')] = total_pts[:, 'home'] 

In [17]: frame[('away', 'totalPTS')] = total_pts[:, 'away'] 

In [18]: frame 
Out[18]: 
    away away home home  away  home 
    team PTS team PTS totalPTS totalPTS 
0 DET 88 CHI 92  88  92 
1 CHI 75 ATL 88  167  88 
2 HOU 105 SEA 95  105  95 
3 TOR 99 DET 97  99  185 
4 DAL 110 STL 100  110  100 
5 STL 85 HOU 74  185  179 
6 MIA 95 CHI 98  95  265 
7 SEA 100 CHI 110  195  375 
Смежные вопросы