Vega-Lite в Markdown: статистические графики текстом
Содержание
Диаграммы Mermaid у нас давно, но у них слабо со статистикой: гистограммы,
регрессии, боксы, хитмапы — не их жанр. Для этого появился новый fence —
vega: описываем график декларативным JSON (спека Vega-Lite), а рендерит
его браузер. Никаких картинок — только текст, как мы любим.
Как это устроено
```vega
{
"width": "container",
"data": {"values": [{"x": 1, "y": 5}]},
"mark": "bar"
}
```
Что происходит под капотом:
- фенс кладёт спеку в
<script type="application/json">внутри контейнера; - клиентский скрипт лениво грузит vega + vega-lite + vega-embed с CDN — только если на странице есть хоть один график;
- при переключении светлой/тёмной темы блога график перерисовывается сам;
- при наведении на график появляется кнопка «Развернуть» — фуллскрин, где интерактивность полностью сохраняется;
- невалидный JSON не роняет страницу, а показывается красным блоком с исходником.
Столбчатая диаграмма
Цены за 1000 токенов из обзора моделей Yandex Cloud:
Наведите курсор на столбцы — тултипы работают без единой строчки нашего JS.
Гистограмма без кнопки зума
Распределение времён ответа (мс). На этом графике висит класс .zoom-0 —
кнопки «Развернуть» у него нет:
.zoom-0 — общий класс отказа от нашего зума: он действует и на картинки,
и на mermaid-схемы (можно вешать на обёртку — например, на весь box).
Точечный график с регрессией
Вот это уже чистый seaborn-жанр: облако точек плюс линия регрессии одним
трансформом regression:
Свечной график с объёмом
Классика биржевых терминалов: тело свечи — от открытия к закрытию, тень — от
минимума до максимума, под ними объёмы тех же дней. Две диаграммы в vconcat,
направление дня считает один трансформ calculate; данные синтетические,
48 торговых дней:
Зелёные свечи — день закрылся выше открытия, красные — ниже. Наведите на свечу: тултип покажет все четыре цены и объём. В развёрнутом виде видно, как всплески объёма совпадают с сильными движениями цены.
Цена, SMA и полосы Боллинджера
Оконные трансформы window считают индикаторы прямо в спеке: короткая
SMA(20) и длинная SMA(50) — скользящие средние двух горизонтов, а лента
Боллинджера — среднее плюс-минус два stdev за 20 дней. Синяя линия — цена,
оранжевый пунктир — SMA(20), зелёная — SMA(50), сиреневая зона — канал
Боллинджера:
К концу периода волатильность растёт — лента расходится ровно затем, чтобы
это показывать. Обратите внимание: линии начинаются не с первого дня, пока
окно не наберет min_periods точек, значения пустые.
Зум осей из коробки
Параметр bind: "scales" даёт нативный pan/zoom прямо в статье: тащите
мышью — двигается график, крутите колесо — зум, двойной клик — сброс:
В развёрнутом виде (кнопка справа вверху) с ним особенно удобно.
Классы работают как у всех фенсов
attr_list на открывающей строке попадает на контейнер:
```vega {: .h-scroll-narrow}
{"...": "..."}
```
— широкий график получит горизонтальный скролл на телефоне, а на десктопе будет вести себя как обычный блок.
А пропорции теперь удобно задавать не числом, а классом .ar-W-H:
высота считается от реальной ширины контейнера (без жёсткого height
из спеки, который на широком экране превращает график в «колбасу»):
```vega {: .ar-16-9}
{"...": "..."}
```
Класс вешаем на открывающую строку фенса — как и у всех фенсов. Если в
спеке заданы width/height числами, скрипт пересчитывает высоту от
реальной ширины, сохраняя пропорцию автора; узкий числовой график при
этом центрируется по контейнеру, а не липнет к левому краю.
Где брать спеки
- Галерея примеров: vega.github.io/vega-lite/examples — сотни готовых спек от баров до карт и кроссфильтров;
- Онлайн-редактор: vega.github.io/editor — покрутили, получили JSON, вставили в статью.
Совет
Ставьте "width": "container" — график впишется в колонку статьи, а не
уедет за край. Данные можно держать прямо в спеке (values), генерировать
(sequence) или подтягивать файлом (data.url — помните про CORS).
В составных диаграммах (vconcat, hconcat, facet) скрипт подставляет
ширину и в дочерние панели сам — в ряду hconcat она делится поровну;
нужен точный контроль — задайте число. Высоту можно выставить классом .ar-W-H на фенсе — она перекрывает фикс-height и считается от реальной ширины.
Комментарии
Пока нет комментариев.
Войдите, чтобы комментировать.