Отто хочет знать, сколько заказов за последние дни доставлено вовремя, а сколько с опозданием. Для этого из сырых колонок надо вычислить новые: день заказа, время доставки в минутах, вердикт «вовремя» или «опоздал». И сохранить результат так, чтобы дашборд за один день не читал все дни. Это работа для встроенных функций Spark и формата Parquet.
Функции вместо циклов
В обычном Python время доставки считали бы циклом по строкам. В Spark так не делают. Вы описываете выражение над колонкой, а Spark применяет его ко всем строкам на всех исполнителях сразу.
Выражения собирают из функций модуля pyspark.sql.functions. Самые нужные:
| Задача | Функции |
|---|---|
| даты и время | to_date, hour, date_trunc, datediff, unix_timestamp, date_format |
| строки | upper, lower, trim, concat_ws, split, regexp_replace |
| числа | round, floor, abs |
| условия | when(...).otherwise(...) |
| пустые значения | coalesce, isNull, isNotNull |
when работает как CASE WHEN в SQL: условия проверяются по порядку, первое истинное даёт значение, а otherwise срабатывает, если ни одно не подошло.
NULL: значения нет
NULL значит «значение неизвестно». У недоставленного заказа нет времени доставки, и в колонке delivered_at стоит NULL. Правила у него такие же, как в SQL:
- арифметика с
NULLдаётNULL: минуты доставки у отменённого заказа будутNULL; - сравнение с
NULLдаётNULL, а неFalse, иfilterтакую строку выбрасывает; count("*")считает все строки, аcount("колонка")иsumпропускаютNULL;coalesce(a, b)берёт первое непустое значение.
Отсюда частая ошибка: filter(F.col("minutes") <= 60) выкинет не только опоздания, но и все недоставленные заказы. Иногда это то, что нужно, а иногда тихая потеря данных.
урок из курса
Урок из курса «Data Engineering». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.