Визуальный разведочный анализ ряда
Первый инструмент аналитика — глаза: рисуем ряд и сразу видим тренд, всплески и подозрительные точки.
Разведочный анализ (EDA) — визуальное и описательное изучение ряда до моделирования: формы тренда, сезонности, выбросов и пропусков.
Зачем смотреть глазами
Ни одна метрика не заменит беглого взгляда на график. За секунды видно: растёт ли ряд, есть ли повторяющиеся пики, нет ли странного провала в данных (сбой выгрузки), нет ли резкого выброса. Многие катастрофы прогноза происходят потому, что аналитик ни разу не нарисовал ряд.
Классический пример — прогноз продаж, обученный на ряде, в котором один день выгрузился нулём из-за сбоя кассовой системы. Метрики этого не подсветят: средние и дисперсии останутся правдоподобными. А вот на графике провал до нуля бросается в глаза мгновенно. Человеческий глаз — поразительно чувствительный детектор аномалий: он эволюционно заточен ловить разрывы паттерна, и в задачах с временными рядами это работает лучше многих автоматических проверок. Поэтому правило простое: прежде чем считать хоть одну модель, нарисуй ряд и просто посмотри на него минуту.
Визуализация ещё и задаёт правильные вопросы. Увидев годовой цикл в трафике сайта, вы зададитесь вопросом «а есть ли внутри ещё недельный?». Заметив, что амплитуда колебаний растёт к концу ряда, вы заранее заподозрите мультипликативную модель. График не даёт ответов сам по себе, но направляет всё дальнейшее исследование — какие гипотезы проверять, какие признаки строить, какую модель пробовать первой.
Отдельно стоит сказать про пропуски и дубликаты — частую беду реальных выгрузок. На графике уровня пропущенные дни нередко превращаются в подозрительно прямые отрезки (так интерполяция «дорисовывает» отсутствующие точки) или в провалы до нуля. Дубликаты, наоборот, дают неестественно ровные плато. Эти артефакты почти невозможно поймать по сводным числам, зато глаз ловит их за секунды. Поэтому опытный аналитик сначала строит ряд, помечает на нём все странности — провалы, плато, одиночные шипы — и только потом решает, чинить данные, выбрасывать участок или оставлять как есть. Пропустить этот шаг значит обучать модель на грязи и потом удивляться её прогнозам.
Рисуем ряд в терминале
Даже без графических библиотек можно построить наглядный ASCII-график: масштабируем значения в ширину строки и печатаем полоски.
sales = [120, 135, 130, 150, 190, 240, 95]
labels = ["Пн","Вт","Ср","Чт","Пт","Сб","Вс"]
lo, hi = min(sales), max(sales)
width = 40
for lab, v in zip(labels, sales):
n = round((v - lo) / (hi - lo) * width)
bar = "#" * n
print(f"{lab} {v:3d} | {bar}")
Вывод:
Пн 120 | ####### Вт 135 | ########### Ср 130 | ########## Чт 150 | ############### Пт 190 | ########################## Сб 240 | ######################################## Вс 95 |
Мгновенно читается: суббота — пик, воскресенье — провал. Это недельная сезонность, а не случайность. Такой график строится за пять строк и экономит часы недопонимания.
Заметьте важную деталь вывода: у воскресенья полоска пустая. Это не баг, а следствие нормировки — воскресный объём 95 является минимумом ряда, а минимум после преобразования (v - lo)/(hi - lo) превращается ровно в ноль и даёт строку нулевой длины. Понимание этой механики избавляет от ложной тревоги: пустая полоса означает «самое низкое значение», а не «нет данных». Когда вы дорастёте до matplotlib или другой графической библиотеки, логика останется той же — просто вместо символов # будут пиксели, а ширину холста зададут не 40 знаков, а размер картинки.
График изменений, а не уровня
Полезно смотреть не только на сам ряд, но и на его приращения — разности соседних точек. На уровне виден тренд, на разностях — резкие скачки и точки разладки.
sales = [120, 135, 130, 150, 190, 240, 95]
diffs = [sales[i] - sales[i-1] for i in range(1, len(sales))]
print("Изменения день-ко-дню:", diffs)
print("Самый резкий скачок:", max(diffs), "падение:", min(diffs))
Вывод:
Изменения день-ко-дню: [15, -5, 20, 40, 50, -145] Самый резкий скачок: 50 падение: -145
Падение -145 в воскресенье — самое заметное событие ряда. На уровне оно тоже видно, но на разностях бросается в глаза сразу.
Почему приращения так полезны? Они убирают общий уровень и оставляют только динамику. Представьте два магазина: один торгует на 1000, другой на 100000, но оба выросли за день на 50. На графике уровня их кривые несопоставимы по масштабу, а на графике приращений видно одно и то же движение «+50». Разности — это, по сути, дискретная производная ряда: где она велика по модулю, там ряд резко меняется. Аналитики специально ищут на графике приращений выбросы вроде нашего -145: такие точки либо помечают реальное событие (закрытие на выходной, акция, авария), либо указывают на ошибку в данных. И то и другое нужно понять до построения модели, иначе единственный выброс перетянет на себя обучение прогноза.
Как работает под капотом
ASCII-график — это нормировка: значение приводится к диапазону [0, ширина] линейным преобразованием (v - min)/(max - min). Тот же принцип лежит в основе любой визуализации: данные масштабируются под физический размер холста. Понимая нормировку, вы не удивитесь, почему минимум всегда «прижат к нулю» — он и есть ноль после преобразования.
У этого преобразования есть и оборотная сторона, о которой стоит помнить. Min-max нормировка крайне чувствительна к выбросам: один аномально большой день растянет hi так, что все остальные полоски сожмутся в неразличимую кашу у левого края. Поэтому в реальных дашбордах часто нормируют не по абсолютному минимуму и максимуму, а по робастным границам (например по 5-му и 95-му процентилю), а выбросы рисуют отдельной отметкой. Это та же идея масштабирования под холст, но устойчивая к экстремумам. Хорошая визуализация — всегда компромисс между честностью (показать всё как есть) и читаемостью (не дать одной точке убить остальную картину).
Частые ошибки
- Сразу строить модель, ни разу не нарисовав ряд, — пропускаются явные сбои данных.
- Смотреть только на уровень и не замечать резких приращений.
- Принимать выброс из-за ошибки выгрузки за настоящий сигнал.
- Нормировать по абсолютным min и max и получать график, раздавленный единственным выбросом.
- Путать пустую полоску (минимум после нормировки) с пропуском в данных.
Итоги
- EDA начинается с визуализации: тренд, сезонность и выбросы часто видны глазами.
- График приращений подсвечивает резкие скачки и точки разладки.
- Даже ASCII-график за пять строк предотвращает грубые ошибки.
- Любая визуализация — это нормировка данных под размер холста; знание её механики защищает от ложных выводов.
- Глаз — мощный детектор аномалий: один взгляд на ряд экономит часы отладки модели.