У меня есть таблица в Bigquery с данными отслеживания для драйверов Nascar (фиктивные данные для проекта, над которым я работаю). Координаты x и y берутся 10 раз в секунду. capture_frame
обозначает текущий кадр, и каждый последовательный capture_frame
должен быть разнесен на 100 миллисекунд, потому что данные берутся каждые 100 мс.
Я хочу рассчитать скорость каждого водителя за круг. Я знаю, как это сделать в пандах, но я думаю, что это возможно в больших запросах. Чтобы вычислить скорость, я смотрю на 2 строки до capture_frame
и 2 строки после, а затем делю на разницу во времени эпохи, которая должна составлять 400 миллисекунд.
Вот пример нескольких кадров захвата на 1 гонку для одного гонщика на первом круге. Есть несколько сотен кадров захвата на круг, а затем смешаны 20 гонщиков, но легче понять, если мы посмотрим только на одного гонщика / гонку / круг.
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
| Race | Capture | Lap | Driver | … | X | Y | Epoch_time | Delta_dist | Curr_speed |
| | _frame | | | | | | | | |
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
| I500 | 1 | 1 | Logano | …. | 2.1 | 1 | 1552089720 | NULL | Null |
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
| I500 | 2 | 1 | Logano | … | 2.2 | 1.1 | 1552089820 | NULL | Null |
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
| I500 | 3 | 1 | Logano | … | 2.22 | 1.2 | 1552089920 | 2.265921446 | 0.005664804 |
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
| I500 | 4 | 1 | Logano | .. | 3.22 | 1.5 | 1552090020 | 3.124163888 | 0.00781041 |
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
| I500 | 5 | 1 | Logano | .. | 4.22 | 1.8 | 1552090120 | NULL | null |
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
| I500 | 6 | 1 | Logano | .. | 5.22 | 1.9 | 1552090220 | NULL | null |
+------+---------+-----+--------+----+------+-----+------------+-------------+-------------+
delta_dist
для кадра 3 рассчитывается как sqrt((4.22-2.1)^2 + (1.8-1)^2)/1
, а curr_speed
- это число, деленное на 400. Первые / последние 2 дистанции и скорости гонки будут равны нулю, так как нет предшествующих x или координаты y, что нормально, поскольку на самом деле скорости нет .1 секунда от старта или остановки.
В пандах я бы это сделал (это не очень хороший код, поскольку я просто привожу каждого гонщика и расу в отдельности):
#laps_per_race dictionary with num laps per race
for driver in driver_list:
for race in race_list:
driver_race_query = “SELECT * from nascar_xyz where driver={driver} and Race={race}”.format(driver=driver, race=race)
df_entire_race = client.query(driver_race_query).to_dataframe()
num_laps = laps_per_race[race]
for lap in num_laps:
#get subset of dataframe just for this lap
df = df_entire_race.loc[df_entire_race['Lap'] == lap]
df.sort_values(‘Epoch_time’, inplace=True)
df[‘prev_x’] = df[‘X’].shift(2)
df[‘next_x’] = df[‘X’].shift(-2)
df[‘prev_y’] = df[‘Y’].shift(2)
df[‘next_y’] = df[‘Y’].shift(-2)
#this is just distance function sqrt((x2-x1)^2 + (y2-y1)^2)
df['delta_dist'] = np.sqrt((df[‘X’].shift(-2) - df[‘X’].shift(2))**2 + (df[‘Y’].shift(-2) - df[‘Y’].shift(2))**2))
#400.0 is the time actual difference
df['Curr_speed'] = df['delta_dist']/400.0
Я думаю, что в моем sql-запросе я должен либо сгруппировать, либо разделить на, потому что я хочу посмотреть каждую расу на driver_id
, а затем на круг (если этот уровень абстракции имеет смысл). Может быть, из-за скорости и предвидения capture_frames я могу что-то сделать с помощью окон (https://cloud.google.com/bigquery/docs/reference/standard-sql/analytic-function-concepts) или что-то, называемое лагом, которое похоже на .shift()
в пандах.