#python #pandas #dataframe
#питон #pandas #фрейм данных
Вопрос:
У меня есть фрейм данных Pandas week1_plays
в следующем формате:
Что я хочу сделать, так это добавить столбец week1_plays['distance_from_receiver']
таким образом, чтобы для каждой строки в фрейме данных мы захватывали ключи gameId, playId, frameId
и находили позиции игрока по x и y с помощью этих ключей и position == 'WR'
. Затем я вычислю расстояние от приемника с помощью следующей функции:
def get_distance(rec_x, rec_y, def_x, def_y):
distance = np.sqrt( ((def_x - rec_x)**2) ((def_y - rec_y)**2) )
return distance
Например, используя предоставленный образец, строка 0, вводимая в функцию, будет
get_distance(91.35, 44.16, 88.89, 36.47)
Текущее решение, которое у меня есть, состоит в том, чтобы использовать лямбда-функцию в фрейме данных как таковую:
week1_topReceivers['distance_from_receiver'] = week1_topReceivers.apply(lambda row: get_distance(week1_wr_position.loc[np.where((week1_topReceivers['playId'] == row['playId']) amp; (week1_topReceivers['frameId'] == row['frameId']) amp; (week1_topReceivers['gameId'] == row['frameId']))]['x'],
week1_topReceivers.loc[np.where((week1_topReceivers['playId'] == row['playId']) amp; (week1_topReceivers['frameId'] == row['frameId']) amp; (week1_topReceivers['gameId'] == row['frameId']))]['y'], row['x'], row['y']), axis = 1)
но запрос фрейма данных для первых двух входных данных занимает очень много времени при большом фрейме данных. Я знаю, что для этого должно быть более оптимальное решение, но мои поиски в Интернете не дают никаких лучших вариантов.
РЕДАКТИРОВАТЬ: Вот большая выборка и ожидаемый результат:
ПРИМЕР
x y o dir event position frameId team gameId playId playDirection route
88.89 36.47 105.63 66.66 None SS 1 home 2018090600 75 left NaN
91.35 44.16 290.45 16.86 None WR 1 away 2018090600 75 left HITCH
86.31 22.01 70.12 168.91 None FS 1 home 2018090600 75 left NaN
73.64 28.70 103.05 219.41 None FS 1 home 2018090600 75 left NaN
86.48 31.12 95.90 33.36 None MLB 1 home 2018090600 75 left NaN
82.67 20.53 81.14 174.57 None CB 1 home 2018090600 75 left NaN
84.00 43.49 108.23 110.32 None CB 1 home 2018090600 75 left NaN
85.63 26.59 87.69 38.80 None LB 1 home 2018090600 75 left NaN
88.89 36.47 105.63 68.49 None SS 2 home 2018090600 75 left NaN
91.37 44.17 290.45 29.61 None WR 2 away 2018090600 75 left HITCH
86.32 22.00 70.88 119.04 None FS 2 home 2018090600 75 left NaN
73.64 28.70 104.57 228.17 None FS 2 home 2018090600 75 left NaN
86.48 31.11 101.10 30.26 None MLB 2 home 2018090600 75 left NaN
82.68 20.53 82.24 147.46 None CB 2 home 2018090600 75 left NaN
84.02 43.49 107.33 106.73 None CB 2 home 2018090600 75 left NaN
85.64 26.61 87.69 37.51 None LB 2 home 2018090600 75 left NaN
88.88 36.47 107.02 57.53 None SS 3 home 2018090600 75 left NaN
91.37 44.17 290.45 32.20 None WR 3 away 2018090600 75 left HITCH
86.33 22.00 71.88 93.49 None FS 3 home 2018090600 75 left NaN
73.63 28.69 104.57 227.74 None FS 3 home 2018090600 75 left NaN
ОЖИДАЕМЫЙ РЕЗУЛЬТАТ:
x y o dir event position frameId team gameId playId playDirection route distance_from_receiver
88.89 36.47 105.63 66.66 None SS 1 home 2018090600 75 left NaN 8.07
91.35 44.16 290.45 16.86 None WR 1 away 2018090600 75 left HITCH 0.00
86.31 22.01 70.12 168.91 None FS 1 home 2018090600 75 left NaN 22.72
73.64 28.70 103.05 219.41 None FS 1 home 2018090600 75 left NaN 23.51
86.48 31.12 95.90 33.36 None MLB 1 home 2018090600 75 left NaN 13.92
82.67 20.53 81.14 174.57 None CB 1 home 2018090600 75 left NaN 25.17
84.00 43.49 108.23 110.32 None CB 1 home 2018090600 75 left NaN 7.38
85.63 26.59 87.69 38.80 None LB 1 home 2018090600 75 left NaN 18.48
88.89 36.47 105.63 68.49 None SS 2 home 2018090600 75 left NaN 8.09
91.37 44.17 290.45 29.61 None WR 2 away 2018090600 75 left HITCH 0.00
86.32 22.00 70.88 119.04 None FS 2 home 2018090600 75 left NaN 22.74
73.64 28.70 104.57 228.17 None FS 2 home 2018090600 75 left NaN 23.53
86.48 31.11 101.10 30.26 None MLB 2 home 2018090600 75 left NaN 13.95
82.68 20.53 82.24 147.46 None CB 2 home 2018090600 75 left NaN 25.19
84.02 43.49 107.33 106.73 None CB 2 home 2018090600 75 left NaN 7.39
85.64 26.61 87.69 37.51 None LB 2 home 2018090600 75 left NaN 18.47
88.88 36.47 107.02 57.53 None SS 3 home 2018090600 75 left NaN 8.09
91.37 44.17 290.45 32.20 None WR 3 away 2018090600 75 left HITCH 0.00
86.33 22.00 71.88 93.49 None FS 3 home 2018090600 75 left NaN 22.74
73.63 28.69 104.57 227.74 None FS 3 home 2018090600 75 left NaN 23.54
Комментарии:
1. я думаю, что здесь можно многое сделать; однако я не могу протестировать образец df, пожалуйста, опубликуйте df и ожидаемый результат
2. спасибо, Кенан, я добавил запрошенные элементы.
Ответ №1:
Вы ищете merge
join
операцию или. Попробуйте что-то вроде этого:
df = pd.DataFrame({'gameId':[1,1,1,1,1,1],'playId':[1,1,1,1,1,1],
'frameId':[1,1,1,2,2,2], 'position':['A','B','WR','C','WR','D'],
'x':[87,56,45,34,45,67], 'y':[25,36,47,365,25,36]})
# create a table with just the wide receiver positions:
wr = df.loc[df.position=='WR'].drop(columns='position')
# merge the wide receiver x,y values into the original table based on the keys:
df = df.merge(wr, how='outer', on=['gameId', 'playId', 'frameId'], suffixes=['', '_wr'])
# apply your function to calculate the column (avoid using apply because it's super slow)
df['dist_from_wr'] = [get_distance(x, y, x_wr, y_wr) for x, y, x_wr, y_wr
in zip(df.x, df.y, df.x_wr, df.y_wr)]
Также обратите внимание, что вам повезло, потому что ваша функция уже векторизована (что не всегда так), поэтому вы можете сделать это еще более эффективно, передавая целые столбцы в качестве входных аргументов следующим образом:
df['dist_from_wr'] = get_distance(df.x, df.y, df.x_wr, df.y_wr)
Результат:
| gameId | playId | frameId | position | x | y | x_wr | y_wr | dist_from_wr |
|-------:|-------:|--------:|:---------|----:|----:|-----:|-----:|-------------:|
| 1 | 1 | 1 | A | 87 | 25 | 45 | 47 | 47.4131 |
| 1 | 1 | 1 | B | 56 | 36 | 45 | 47 | 15.5563 |
| 1 | 1 | 1 | WR | 45 | 47 | 45 | 47 | 0 |
| 1 | 1 | 2 | C | 34 | 365 | 45 | 25 | 340.178 |
| 1 | 1 | 2 | WR | 45 | 25 | 45 | 25 | 0 |
| 1 | 1 | 2 | D | 67 | 36 | 45 | 25 | 24.5967 |