Ответ
Расчет задержки рейса — это классическая задача анализа временных рядов, где ключевым показателем является разница между фактическим и запланированным временем.
Базовый расчет с использованием pandas:
Предположим, у нас есть колонки с временем прибытия в формате datetime.
import pandas as pd
# Загрузка данных
df = pd.read_csv('flights.csv', parse_dates=['scheduled_arrival', 'actual_arrival'])
# Расчет задержки в минутах.
# Положительное значение = опоздание, отрицательное = прибытие раньше расписания.
df['arrival_delay_minutes'] = (df['actual_arrival'] - df['scheduled_arrival']).dt.total_seconds() / 60
# Просмотр статистики
print(df['arrival_delay_minutes'].describe())
Обработка типичных проблем в данных:
-
Переход через полночь: Если рейс запланирован на 23:50, а прибыл в 00:15, простая разница даст отрицательное значение. Нужна коррекция:
def calculate_delay(scheduled, actual): delay = (actual - scheduled).total_seconds() / 60 # Если задержка меньше -12 часов (720 мин), вероятно, переход через полночь в сторону опоздания if delay < -720: delay += 24 * 60 # Добавляем сутки в минутах # Если задержка больше +18 часов, вероятно, раннее прибытие с переходом через полночь назад elif delay > 1080: delay -= 24 * 60 return delay df['arrival_delay_minutes'] = df.apply( lambda row: calculate_delay(row['scheduled_arrival'], row['actual_arrival']), axis=1 ) -
Отсутствующие и аномальные значения:
# Удаление записей, где время прибытия отсутствует df_clean = df.dropna(subset=['actual_arrival', 'scheduled_arrival']) # Фильтрация физически невозможных задержек (например, > 2 суток или < -5 часов) df_clean = df_clean[(df_clean['arrival_delay_minutes'] > -300) & (df_clean['arrival_delay_minutes'] < 48*60)]
Агрегация и анализ:
# Средняя и медианная задержка по авиакомпании
agg_stats = df_clean.groupby('airline')['arrival_delay_minutes'].agg(['mean', 'median', 'std', 'count'])
print(agg_stats.sort_values('median'))
# Доля рейсов с опозданием более 15 минут
df_clean['is_delayed_15min'] = df_clean['arrival_delay_minutes'] > 15
delay_rate = df_clean.groupby('origin_airport')['is_delayed_15min'].mean() * 100
Для прогнозирования временных рядов этот признак arrival_delay_minutes часто является целевой переменной. Важно также создать лаговые признаки (задержки предыдущих рейсов того же самолета/маршрута) и признаки времени (час дня, день недели, месяц).
Ответ 18+ 🔞
А, ну это ж классика, ебать мои старые костыли! Каждый, кто хоть раз пытался понять, почему его самолёт торчит на полосе, а не у него в аэропорту, в итоге упрётся в эту самую задачу. Считаем, на сколько наш железный конь опоздал.
Вот смотри, основа основ — это просто взять и вычесть одно время из другого. Всё вроде бы просто, как два пальца обоссать, но в данных всегда найдётся какая-нибудь манда с ушами.
import pandas as pd
# Загрузка данных
df = pd.read_csv('flights.csv', parse_dates=['scheduled_arrival', 'actual_arrival'])
# Расчет задержки в минутах.
# Положительное значение = опоздание, отрицательное = прибытие раньше расписания.
df['arrival_delay_minutes'] = (df['actual_arrival'] - df['scheduled_arrival']).dt.total_seconds() / 60
# Просмотр статистики
print(df['arrival_delay_minutes'].describe())
Выполнил это — и сразу удивление пиздец. Оказывается, у тебя половина рейсов прилетела на 20 часов раньше, а вторая — улетела в будущее. Потому что главный подводный камень — переход через полночь. Самолёт по расписанию в 23:50, а припёрся в 00:15. Компьютер тупо вычтет и скажет, что он прилетел на 23 часа и 35 минут раньше. Хуй с горы, а не результат.
def calculate_delay(scheduled, actual):
delay = (actual - scheduled).total_seconds() / 60
# Если задержка меньше -12 часов (720 мин), вероятно, переход через полночь в сторону опоздания
if delay < -720:
delay += 24 * 60 # Добавляем сутки в минутах
# Если задержка больше +18 часов, вероятно, раннее прибытие с переходом через полночь назад
elif delay > 1080:
delay -= 24 * 60
return delay
df['arrival_delay_minutes'] = df.apply(
lambda row: calculate_delay(row['scheduled_arrival'], row['actual_arrival']), axis=1
)
Дальше — святое дело: почистить данные. Потому что обязательно найдётся запись, где время прибытия — это NaT, или какой-нибудь распиздяй вручную вбил дату 1900 года. А ещё физические ограничения: ну не может Boeing 737 опоздать на две недели, это уже не задержка, а кругосветное путешествие.
# Удаление записей, где время прибытия отсутствует
df_clean = df.dropna(subset=['actual_arrival', 'scheduled_arrival'])
# Фильтрация физически невозможных задержек (например, > 2 суток или < -5 часов)
df_clean = df_clean[(df_clean['arrival_delay_minutes'] > -300) & (df_clean['arrival_delay_minutes'] < 48*60)]
Ну а когда с базой покончили, начинается самое интересное — агрегация. Тут можно узнать, какая авиакомпания — полупидор, которая вечно всех задерживает, а какой аэропорт — настоящая хитрая жопа, из которой всегда вылетают по расписанию.
# Средняя и медианная задержка по авиакомпании
agg_stats = df_clean.groupby('airline')['arrival_delay_minutes'].agg(['mean', 'median', 'std', 'count'])
print(agg_stats.sort_values('median'))
# Доля рейсов с опозданием более 15 минут
df_clean['is_delayed_15min'] = df_clean['arrival_delay_minutes'] > 15
delay_rate = df_clean.groupby('origin_airport')['is_delayed_15min'].mean() * 100
А если ты хочешь не просто посчитать, а спрогнозировать эту самую задержку, то эта колонка arrival_delay_minutes и будет твоей священной целью. Только не забудь накрутить фичей вокруг да около: задержки предыдущих рейсов этого самолёта, час дня, день недели. Потому что в понедельник утром в «Шереметьево» — это ёперный театр и овердохуища народу, а не просто время суток. Вот тогда модель и заработает как надо.