Привязки и виджеты
Зная типы параметров и условия, можно связывать параметры с элементами диаграммы, например легендами, и виджетами, например списками и ползунками. Для этого используется bind внутри param и selection. Согласно документации привязок Vega-Lite, доступны три подхода:
- Точечный и интервальный выбор для интерактивности на основе данных: выделения и фильтрации по значениям.
- Ползунки и флажки для интерактивности на основе логики: выделения и фильтрации по значениям самих виджетов.
- Привязка интервального выбора к шкале, например для масштабирования карты.
Vega-Lite поддерживает следующие элементы ввода:
| Элемент | Описание | Пример |
|---|---|---|
binding_checkbox |
Флажки, позволяющие выбирать несколько элементов. | Несколько видов взаимодействия |
binding_radio |
Переключатели с выбором только одного варианта. | Несколько видов взаимодействия |
binding_select |
Раскрывающийся список для выбора одного элемента. | Несколько видов взаимодействия |
binding_range |
Ползунок для выбора значения по шкале. | Население США во времени |
binding |
Общий способ, поддерживающий многие элементы ввода HTML. |
Привязка виджетов
Виджеты — элементы HTML: списки, ползунки, переключатели и поля поиска. Переменные и параметры выбора можно сочетать с ними тремя способами: поиск по данным, сравнение с данными и сравнение по логике.
Поиск по значениям данных
Активные значения виджета вместе с параметром selection позволяют найти точки с совпадающими значениями в наборе данных. Например, свяжем список с точечным выбором, чтобы выделять автомобили заданного Origin:
import altair as alt
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)
color = (
alt.when(selection)
.then(alt.Color("Origin:N").legend(None))
.otherwise(alt.value("lightgray"))
)
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color=color,
).add_params(
selection
)
Хотя в списке с начала отображается выбранное значение, для реального начального выбора на диаграмме нужно задать value=. Это тот же подход, что и для переменных; пример приведён ниже в привязке канала кодирования.
Диаграмма по-прежнему реагирует на выбор через условия, как и без виджетов. Привязки позволяют также фильтровать данные, оставляя только выбранные точки.
В следующем примере добавлен пустой выбор, возвращающий все точки после выбора через переключатель или список, где нельзя просто отменить выбранный вариант:
# Make radio button less cramped by adding a space after each label
# The spacing will only show up in your IDE, not on this doc page
options = ['Europe', 'Japan', 'USA']
labels = [option + ' ' for option in options]
input_dropdown = alt.binding_radio(
# Add the empty selection which shows all when clicked
options=options + [None],
labels=labels + ['All'],
name='Region: '
)
selection = alt.selection_point(
fields=['Origin'],
bind=input_dropdown,
)
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
# We need to set a constant domain to preserve the colors
# when only one region is shown at a time
color=alt.Color('Origin:N').scale(domain=options),
).add_params(
selection
).transform_filter(
selection
)
Через общую функцию binding доступны и другие HTML-виджеты. Ниже поле поиска выделяет точки с точным совпадением строки. Наведите указатель на точку, посмотрите название автомобиля и введите его целиком, например vw pickup:
search_input = alt.selection_point(
fields=['Name'],
empty=False, # Start with no points selected
bind=alt.binding(
input='search',
placeholder="Car model",
name='Search ',
)
)
alt.Chart(data.cars.url).mark_point(size=60).encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
tooltip='Name:N',
opacity=alt.when(search_input).then(alt.value(1)).otherwise(alt.value(0.05)),
).add_params(
search_input
)
Точное совпадение не всегда удобно. В разделе выражений показан поиск по частичной строке через регулярное выражение.
Сравнение с данными
Выборы удобны для поиска точного совпадения, но иногда нужно сравнение: например, выделить точки выше или ниже порога ползунка. Для этого рекомендуется переменная через param.
Синтаксис datum.xval обращается к столбцу данных. Префикс datum сообщает Altair, что сравнивается поле DataFrame, а не переменная Python xval, как в записи xval < selector:
import numpy as np
import pandas as pd
rand = np.random.RandomState(42)
df = pd.DataFrame({
'xval': range(100),
'yval': rand.randn(100).cumsum()
})
slider = alt.binding_range(min=0, max=100, step=1, name='Cutoff ')
selector = alt.param(name='SelectorName', value=50, bind=slider)
predicate = alt.datum.xval < selector
alt.Chart(df).mark_point().encode(
x='xval',
y='yval',
color=alt.when(predicate).then(alt.value("red")).otherwise(alt.value("blue")),
).add_params(
selector
)
В этом случае можно использовать и параметр выбора: его значения доступны выражениям. Вот ползунок порога и цвет в зависимости от того, ниже или выше него находится точка:
slider = alt.binding_range(min=0, max=100, step=1, name='Cutoff ')
selector = alt.selection_point(
name="SelectorName",
fields=['cutoff'],
bind=slider,
value=[{'cutoff': 50}]
)
predicate = alt.datum.xval < selector.cutoff
alt.Chart(df).mark_point().encode(
x='xval',
y='yval',
color=alt.when(predicate).then(alt.value("red")).otherwise(alt.value("blue")),
).add_params(
selector
)
Знать способ доступа к значениям выбора полезно, но для простых взаимодействий переменные параметров, введённые в Altair 5, часто удобнее. Они также доступны в строках выражений.
Для поиска точного значения можно использовать равенство, например alt.datum.xval == selector, но часто удобнее параметр выбора с явно указанным полем или кодированием.
Сравнение по логике
Логическое сравнение основано на правилах и условиях, а не на самих значениях данных. Например, для флажка нужно проверить, отмечен он или нет, и выполнить действие.
В таком переключателе используется param, а не selection_point: нас интересует состояние флажка True/False, а не наличие этих значений в данных:
bind_checkbox = alt.binding_checkbox(name='Scale point size by "Acceleration": ')
param_checkbox = alt.param(bind=bind_checkbox)
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
size=alt.when(param_checkbox).then("Acceleration:Q").otherwise(alt.value(25)),
).add_params(
param_checkbox
)
Другой виджет, независимый от данных, — выбор цвета через общую функцию binding. Здесь пользователь интерактивно задаёт цвета диаграммы:
color_usa = alt.param(value="#317bb4", bind=alt.binding(input='color', name='USA '))
color_europe = alt.param(value="#ffb54d", bind=alt.binding(input='color', name='Europe '))
color_japan = alt.param(value="#adadad", bind=alt.binding(input='color', name='Japan '))
alt.Chart(data.cars.url).mark_circle().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color=alt.Color(
'Origin:N',
scale=alt.Scale(
domain=['USA', 'Europe', 'Japan'],
range=[color_usa, color_europe, color_japan]
)
)
).add_params(
color_usa, color_europe, color_japan
)
Привязка легенды
Интерактивная легенда помогает сосредоточиться на группах данных. Вместо самостоятельного построения отдельной диаграммы-легенды Altair предоставляет bind='legend' для легенды, элементы которой выбираются щелчком:
selection = alt.selection_point(fields=['Origin'], bind='legend')
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N',
opacity=alt.when(selection).then(alt.value(0.8)).otherwise(alt.value(0.2)),
).add_params(
selection
)
Привязка шкал
Для интервального выбора bind="scales" автоматически связывает выбор с перемещением и масштабированием диаграммы:
selection = alt.selection_interval(bind='scales')
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N',
).add_params(
selection
)
Это распространённый подход, поэтому метод interactive предоставляет более короткую запись:
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N',
).interactive()
Привязка канала кодирования
Чтобы выбор виджета менял отображаемые столбцы, нужна связь с каналом кодирования. В отличие от легенд и шкал, задать её при создании выбора, например через bind='x', нельзя.
Значение параметра можно передать каналу. Это гибче, но пока issue #7365 не решён, нужно отдельное вычисляемое преобразование.
В примере значение параметра доступно по имени. Индексирование данных через datum[] извлекает выбранный столбец и передаёт его значения каналу x:
dropdown = alt.binding_select(
options=['Horsepower', 'Displacement', 'Weight_in_lbs', 'Acceleration'],
name='X-axis column '
)
xcol_param = alt.param(
value='Horsepower',
bind=dropdown
)
alt.Chart(data.cars.url).mark_circle().encode(
x=alt.X('x:Q').title(''),
y='Miles_per_Gallon:Q',
color='Origin:N'
).transform_calculate(
x=alt.datum[xcol_param]
# x=f'datum[{xcol_param.name}]' # Also works
).add_params(
xcol_param
)
Параметры внутри calculate позволяют задавать динамические вычисления, например вычитать разные пары столбцов. См. интерактивный выбор столбца. Там заголовок диаграммы тоже обновляется выражением с параметром; подробнее см. доступ к значениям параметров.
Сейчас заголовки осей нельзя динамически менять по выбранному параметру. Пока issue #7264 не решён, можно вместо заголовка использовать текстовый примитив; такой подход показан в ответе Stack Overflow «Can I turn Altair axis titles into links?».