Выражения

Altair использует язык выражений Vega для пользовательской интерактивности и простых формул. Это определённый набор операций в стиле JavaScript.

Модуль expr предоставляет константы и функции для записи выражений с синтаксисом Python. Altair поддерживает оба варианта. Вводные примеры приведены в преобразовании Calculate; рекомендуем начать с них.

Выражения внутри параметров

Создадим ползунок, связанный с параметром param_width, и два выражения через param: одно с синтаксисом JavaScript, другое Python. В JavaScript к значению обращаются через f"{param_width.name}", в Python достаточно имени переменной.

Выражения можно связать с параметром канала, например цветом заголовка оси. При значении ниже 200 цвет красный, иначе чёрный:

import altair as alt
import numpy as np
import pandas as pd

rand = np.random.RandomState(42)
df = pd.DataFrame({
    'xval': range(100),
    'yval': rand.randn(100).cumsum()
})

bind_range = alt.binding_range(min=100, max=300, name='Slider value:  ')
param_width = alt.param(bind=bind_range)

# Examples of how to write both js and python expressions
param_color_js_expr = alt.param(expr=f"{param_width.name} < 200 ? 'red' : 'black'")
param_color_py_expr = alt.param(expr=alt.expr.if_(param_width < 200, 'red', 'black'))

chart = alt.Chart(df).mark_point().encode(
    alt.X('xval').axis(titleColor=param_color_js_expr),
    alt.Y('yval').axis(titleColor=param_color_py_expr)
).add_params(
    param_width,
    param_color_js_expr,
    param_color_py_expr
)
chart

Тернарный оператор JavaScript f"{param_width.name} < 200 ? 'red' : 'black'" эквивалентен функции Python expr.if_(param_width < 200, 'red', 'black'). Выражения, определённые как параметры, нужно добавить в диаграмму через .add_params().

Встроенные выражения

Функция expr() позволяет задать выражение непосредственно в спецификации. Встроенное выражение не является параметром, поэтому не требует add_params: это короткая альтернатива полной записи параметра.

Изменим предыдущую диаграмму, чтобы размер точек зависел от значения выражения. Вместо условия используем значение напрямую, указав только имя параметра:

chart.mark_point(size=param_width)

Помимо параметров mark_*, выражения можно передавать как значение канала кодирования. Вот тот же результат другим способом:

chart.encode(size=alt.value(param_width))

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

bind_range = alt.binding_range(min=100, max=300, name='Chart width: ')
param_width = alt.param('width', bind=bind_range)

alt.Chart(df).mark_point().encode(
    alt.X('xval'),
    alt.Y('yval')
).add_params(
    param_width
)

Встроенные выражения в заголовках

Выражение может обновлять заголовок, показывая текущее значение параметра. Расширим предыдущий пример f-строкой внутри выражения. Дополнительные кавычки и знаки плюс нужны для правильной интерпретации значения:

bind_range = alt.binding_range(min=100, max=300, name='Chart width: ')
param_width = alt.param('width', bind=bind_range)

# In Javascript, a number is converted to a string when added to an existing string,
# which is why we use this nested quotation.
title=alt.Title(alt.expr(f'"This chart is " + {param_width.name} + " px wide"'))
alt.Chart(df, title=title).mark_point().encode(
    alt.X('xval'),
    alt.Y('yval')
).add_params(
    param_width
)

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

from altair.datasets import data

cars = data.cars.url
input_dropdown = alt.binding_select(options=['Europe', 'Japan', 'USA'], name='Region ')
selection = alt.selection_point(fields=['Origin'], bind=input_dropdown, value='Europe')

title = alt.Title(alt.expr(f'"Cars from " + {selection.name}.Origin'))

alt.Chart(cars, title=title).mark_point().encode(
    x='Horsepower:Q',
    y='Miles_per_Gallon:Q',
).add_params(
    selection
).transform_filter(
    selection
)

Поиск по регулярному выражению

Улучшить поиск можно с помощью регулярного выражения. expr.regexp задаёт шаблон, а expr.test проверяет его по строке, здесь по полю Name. Параметр i отключает чувствительность к регистру.

Здесь используется param, а не selection_point, поскольку это сложнее точного поиска значения. Попробуйте ввести mazda|ford:

search_input = alt.param(
    value='',
    bind=alt.binding(
        input='search',
        placeholder="Car model",
        name='Search ',
    )
)
search_matches = alt.expr.test(alt.expr.regexp(search_input, "i"), alt.datum.Name)

alt.Chart(cars).mark_point(size=60).encode(
    x='Horsepower:Q',
    y='Miles_per_Gallon:Q',
    tooltip='Name:N',
    opacity=alt.when(search_matches).then(alt.value(1)).otherwise(alt.value(0.05)),
).add_params(search_input)

Вся интерактивность выполняется на стороне клиента. Диаграмму можно сохранить как HTML или разместить на статическом сайте, например GitHub/GitLab Pages: пользоваться ею можно без установки Python.

Кратко о выражениях

  • Язык выражений Vega задаёт простые формулы для пользовательского взаимодействия.
  • Поддерживаются синтаксис JavaScript и синтаксис Python.
  • Модуль expr предоставляет запись выражений средствами Python.
  • Выражения включаются в спецификацию через определение параметра param(expr=...) или напрямую через expr(...).
  • Они применимы там, где документация допускает ExprRef: прежде всего в свойствах примитивов, параметрах каналов и определениях значений каналов. Также поддерживаются в заголовке диаграммы, но пока не в подзаголовках и заголовках направляющих — осей и легенд. Подробнее см. issue #7408.