У меня есть датафрейм с прогнозом прибытия автобусной остановки:

path_id | forecast | forecast_made_at | bus_id
 int    | datetime |  datetime        | int

Мы делаем прогнозы каждые 5 минут, поэтому записи в базе данных могут дублироваться. Например

In 11:50 we predict bus #11544 will arrive at 11:59
In 11:50 we predict bus #95447 will arrive at 11:55
--......--
In 11:55 we predict bus #11544 will arrive at 12:02

Я хочу получить новейший прогноз с самым большим параметром прогноза_сделано_ат:

res = pd.DataFrame()
for k, row in t_data.iterrows():
  prediction = dict(**row)
  forecasts = t_data[t_data["bus_id"] == prediction["bus_id"]] # Forecasts with the same bus_id
  prediction["best"] = (prediction["forecast_made_at"] == max(forecasts["forecast_made_at"]))
  res = res.append(prediction, ignore_index=True)

res = res[res["best"] == True]

В этом коде мы работаем со словарями, а не с объектами pandas, поэтому он очень медленный. Как я могу сделать это с помощью инструментов панд

0
BlueScreen 21 Янв 2022 в 18:22
Можете ли вы предоставить несколько строк вашего фрейма данных, пожалуйста?
 – 
Daniele Bianco
21 Янв 2022 в 18:33
(55, 12:07, 12:00, 12:31), (55, 12:11, 12:00, 1789), (55, 12:08, 12:05:, 1231)
 – 
BlueScreen
21 Янв 2022 в 18:40

3 ответа

Лучший ответ

Что вам нужно, так это сочетание группировки по bus_id, сортировки по дате и выбора самой последней строки.

Один из вариантов — удаление дубликатов bus_id и сохранение только самой последней записи:

t_data.sort_values('forecast_made_at').drop_duplicates(subset=['bus_id'], keep='last')

Другой вариант: группировка по bus_id и выбор последней записи:

t_data.sort_values('forecast_made_at').groupby('bus_id').last().reset_index()
2
ozacha 21 Янв 2022 в 18:39

Использование этого фрейма данных в качестве примера

   path_id            forecast    forecast_made_at  bus_id
0        1 2018-01-01 14:10:00 2018-01-01 11:10:00       7
1        1 2018-01-01 14:10:00 2018-01-01 10:15:00       7
2        1 2018-01-01 14:10:00 2018-01-01 10:49:00       7
3        2 2018-09-10 03:05:00 2018-09-09 23:05:00       6
4        2 2018-09-10 03:05:00 2018-09-10 03:00:00       6
5        2 2018-09-10 03:05:00 2018-09-10 01:30:00       6
6        3 2018-04-21 17:32:00 2018-04-21 17:31:00       4
7        3 2018-04-21 17:32:00 2018-04-21 17:12:00       4
8        3 2018-04-21 17:32:00 2018-04-21 17:02:00       4

Вы можете добиться этого с помощью следующего

new_df = df.loc[df.groupby('forecast')['forecast_made_at'].idxmax()]
print(new_df)

   path_id            forecast    forecast_made_at  bus_id
0        1 2018-01-01 14:10:00 2018-01-01 11:10:00       7
6        3 2018-04-21 17:32:00 2018-04-21 17:31:00       4
4        2 2018-09-10 03:05:00 2018-09-10 03:00:00       6
1
BrendanA 21 Янв 2022 в 18:37

Это генерирует индекс, содержащий «bus_id» и максимальное значение «forecast_made_at» для этого «bus_id».

ids = df.groupby("bus_id", as_index=False).forecast_made_at.max().set_index(["bus_id", "forecast_made_at"]).index

Затем мы можем извлечь данные, соответствующие этому индексу, из исходного кадра данных как:

df.set_index(["bus_id", "forecast_made_at"]).loc[ids].reset_index()

Надеюсь, это будет полезно.

0
Daniele Bianco 21 Янв 2022 в 18:47