Как рассчитать величину задержки рейса в минутах по историческим данным о перелетах?

«Как рассчитать величину задержки рейса в минутах по историческим данным о перелетах?» — вопрос из категории Временные ряды, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Расчет задержки рейса — это классическая задача анализа временных рядов, где ключевым показателем является разница между фактическим и запланированным временем.

Базовый расчет с использованием 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())

Обработка типичных проблем в данных:

  1. Переход через полночь: Если рейс запланирован на 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
    )
  2. Отсутствующие и аномальные значения:

    # Удаление записей, где время прибытия отсутствует
    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 часто является целевой переменной. Важно также создать лаговые признаки (задержки предыдущих рейсов того же самолета/маршрута) и признаки времени (час дня, день недели, месяц).