Определить победителя игры по столбцу очков с пандами - PullRequest
0 голосов
/ 26 декабря 2018

Я настраиваю набор данных хоккейных игр и должен решить, выиграла или проиграла команда, на основе столбцов 'Game_id' и 'Goals'.Каждая игра имеет свой собственный идентификатор и занимает две строки, поэтому 1000 игр хранятся в 2000 строках.

Мой фрейм данных выглядит следующим образом:

Team  Home/Away  Goals  Game_id
CAL   Home       7      2017020001
PHY   Away       4      2017020001
CAP   Home       7      2017020002
WILD  Away       4      2017020002

Мне нужен пятый столбец 'Won/Lost', которыйосновано на целях для конкретного 'Game_id'.Я изо всех сил пытаюсь создать цикл, который делает это для меня.

Результат, который я ищу, таков:

Team  Home/Away  Goals  Game_id      Won/Lost
CAL   Home       7      2017020001   Won
PHY   Away       4      2017020001   Lost
CAP   Home       7      2017020002   Won
WILD  Away       4      2017020002   Lost

1 Ответ

0 голосов
/ 26 декабря 2018

Учитывая

>>> df                                                                                                                  
   Team Home/Away  Goals     Game_id
0   CAL      Home      7  2017020001
1   PHY      Away      4  2017020001
2   CAP      Home      7  2017020002
3  WILD      Away      4  2017020002
4  WILD      Away      1  2017020003
5   CAP      Home      1  2017020003

Я написал бы следующую функцию:

def win_loss_draw(group): 
     group = group == group.max() 
     if group.all(): 
         group[:] = 'Draw' 
     else: 
         group = group.map({True: 'Won', False: 'Lost'}) 
     return group

... и применил бы ее так:

>>> df['Won/Lost'] = df.groupby('Game_id')['Goals'].apply(win_loss_draw)                                                
>>> df                                                                                                                  
   Team Home/Away  Goals     Game_id Won/Lost
0   CAL      Home      7  2017020001      Won
1   PHY      Away      4  2017020001     Lost
2   CAP      Home      7  2017020002      Won
3  WILD      Away      4  2017020002     Lost
4  WILD      Away      1  2017020003     Draw
5   CAP      Home      1  2017020003     Draw

Я исключаю ничьи, учитывая, что хоккейная игра может закончиться ничьей только в обычное время, но мои данные с течением времени, поэтому есть только выигрыш и проигрыш

В данном конкретном случае этодостаточно для выдачи

df['Won/Lost'] = df.groupby('Game_id')['Goals'].apply(lambda g: (g == g.max()).map({True: 'Won', False: 'Lost'}))

(это Версия 1)

~ edit ~

Улучшения производительности!

Версия2:

is_winner = df.groupby('Game_id')['Goals'].transform('max') == df['Goals']
df['Won/Lost'] = is_winner.map({True: 'Won', False: 'Lost'})

Версия 3:

is_winner = df.groupby('Game_id')['Goals'].transform('max') == df['Goals']                                          
df['Won/Lost'] = np.where(is_winner.values, 'Won', 'Lost')

Время:

# Setup
>>> df = pd.concat([df]*1000, ignore_index=True)                                                                        
>>> df['Game_id'] = np.arange(len(df)//2).repeat(2)                                                                     
>>>                                                                                                                     
>>> df                                                                                                                  
      Team Home/Away  Goals  Game_id
0      CAL      Home      7        0
1      PHY      Away      4        0
2      CAP      Home      7        1
3     WILD      Away      4        1
4      CAL      Home      7        2
...    ...       ...    ...      ...
3995  WILD      Away      4     1997
3996   CAL      Home      7     1998
3997   PHY      Away      4     1998
3998   CAP      Home      7     1999
3999  WILD      Away      4     1999

# Timings (i5-6200U CPU @ 2.30GHz, only relative times are important though)
>>> %timeit df.groupby('Game_id')['Goals'].apply(lambda g: (g == g.max()).map({True: 'Won', False: 'Lost'})) # Version 1            
1.73 s ± 13.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
>>> %timeit (df.groupby('Game_id')['Goals'].transform('max') == df['Goals']).map({True: 'Won', False: 'Lost'}) # Version 2          
2.38 ms ± 37.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit np.where((df.groupby('Game_id')['Goals'].transform('max') == df['Goals']).values, 'Won', 'Lost') # Version 3            
1.53 ms ± 6.19 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
...