Основы статистической визуализации

Этот урок адаптирован из вводного урока Vega-Lite.

Здесь мы пройдём основные шаги создания визуализаций в Altair. Сначала убедитесь, что пакет Altair и его зависимости установлены.

Предполагается, что вы работаете в интерфейсе блокнотов Jupyter — например, JupyterLab, Colab или VS Code, — где диаграммы отображаются автоматически. Если вы используете другую среду, сначала прочитайте об отображении диаграмм Altair.

Содержание урока:

Данные

Работа с данными в Altair строится вокруг pandas DataFrame. Одна из особенностей статистической визуализации — использование упорядоченных (tidy) таблиц данных. Для этого урока импортируем pandas и создадим простой DataFrame: столбец a содержит категориальную переменную, а b — числовую.

import pandas as pd
data = pd.DataFrame({'a': list('CCCDDDEEE'),
                     'b': [2, 7, 4, 1, 2, 6, 8, 4, 7]})

Чаще всего данные передают в Altair в виде DataFrame. Имена столбцов таблицы играют важную роль при построении диаграмм, как мы увидим далее.

Объект Chart

Основной объект Altair — Chart. При его создании DataFrame передаётся единственным аргументом:

import altair as alt
chart = alt.Chart(data)

Объект диаграммы уже создан, но мы ещё не указали, что он должен делать с данными. Это следующий шаг.

Кодирование и графические примитивы

Теперь зададим, как нужно показывать данные. Для этого используется атрибут mark объекта диаграммы, с которым удобнее всего работать через методы Chart.mark_*. Например, чтобы представить данные точками, вызовем Chart.mark_point:

alt.Chart(data).mark_point()

Каждой строке набора данных соответствует точка. Все точки находятся друг над другом, поскольку мы ещё не задали их положения.

Чтобы разделить точки визуально, свяжем столбцы данных с каналами кодирования, или просто каналами. Например, переменную a можно закодировать каналом x, который определяет положение точки по оси x. Для этого используется метод Chart.encode:

alt.Chart(data).mark_point().encode(
    x='a',
)

Метод encode() задаёт соответствия между каналами — x, y, color, shape, size и другими — и столбцами набора данных, указанными по имени.

При работе с pandas DataFrame Altair автоматически определяет тип данных столбца. В этом примере он номинальный: значения представляют категории без определённого порядка.

Мы разделили точки по одному признаку, но внутри каждой категории они по-прежнему перекрываются. Добавим канал y и свяжем его со столбцом b:

alt.Chart(data).mark_point().encode(
    x='a',
    y='b'
)

Altair также автоматически определяет тип столбца b: теперь он количественный, то есть содержит числовые значения. Линии сетки и подходящие заголовки осей тоже добавляются автоматически.

Преобразование данных: агрегирование

Altair содержит встроенный синтаксис агрегирования, который позволяет гибче представлять данные. Например, среднее значение можно вычислить, указав операцию агрегирования внутри обозначения столбца:

alt.Chart(data).mark_point().encode(
    x='a',
    y='average(b)'
)

Теперь каждой категории по оси x соответствует одна точка, показывающая среднее значение внутри категории.

Агрегированные значения часто показывают столбцами. Заменим Chart.mark_point на Chart.mark_bar:

alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)'
)

Категориальный признак связан с осью x, поэтому получилась диаграмма с вертикальными столбцами. Для горизонтальной достаточно поменять местами аргументы x и y:

alt.Chart(data).mark_bar().encode(
    y='a',
    x='average(b)'
)

Отступление: просмотр JSON

Основная задача Altair — преобразовать описание диаграммы в строку JSON, соответствующую схеме Vega-Lite. С помощью метода Chart.to_json можно посмотреть спецификацию, которую Altair формирует и передаёт в Vega-Lite:

chart = alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)',
)
print(chart.to_json())

Сокращённая запись encode(x='a') разворачивается в JSON-структуру с именем поля field и типом данных type. Запись для канала y разворачивается аналогично и дополнительно содержит свойство aggregate.

Полный сокращённый синтаксис Altair также позволяет явно указать тип столбца:

y = alt.Y('average(b):Q')
print(y.to_json())

Это эквивалентно записи с именованными параметрами:

y = alt.Y(field='b', type='quantitative', aggregate='average')
print(y.to_json())

Такой подробный способ задания каналов можно использовать непосредственно в спецификации диаграммы Altair. Это полезно при работе с более сложными настройками полей:

alt.Chart(data).mark_bar().encode(
    alt.Y('a', type='nominal'),
    alt.X('b', type='quantitative', aggregate='average')
)

Настройка визуализации

По умолчанию Altair и Vega-Lite самостоятельно выбирают некоторые свойства диаграммы. API Altair позволяет изменить её оформление. Например, заголовки осей можно задать методом title классов каналов, а цвет примитивов — аргументом color метода Chart.mark_*, передав допустимую строку цвета HTML:

alt.Chart(data).mark_bar(color='firebrick').encode(
    alt.Y('a').title('категория'),
    alt.X('average(b)').title('среднее b по категориям')
)

Публикация визуализации

Готовую визуализацию можно опубликовать в интернете с помощью JavaScript-пакета Vega-Embed. Для любой диаграммы метод Chart.save создаёт самостоятельный HTML-документ:

chart = alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)',
)
chart.save('chart.html')

Базовый HTML-шаблон имеет следующий вид. JSON-спецификацию, полученную с помощью Chart.to_json, нужно поместить в JavaScript-переменную spec:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/vega@3"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-lite@2"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-embed@3"></script>
  </head>
  <body>
    <div id="vis"></div>
    <script type="text/javascript">
      var spec = {};  /* JSON-спецификация диаграммы */
      var opt = {"renderer": "canvas", "actions": false};  /* Настройки встраивания */
      vegaEmbed("#vis", spec, opt);
    </script>
  </body>
</html>

Метод Chart.save позволяет удобно сохранить такой HTML в файл. Подробнее о встраивании Altair и Vega-Lite рассказано в документации проекта Vega-Embed.