绑定与微件#
了解参数类型和条件后,您现在可以将参数绑定到图表元素(例如图例)和微件(例如下拉列表和滑块)。这是通过在 param
和 selection
中使用 bind
选项来完成的。根据Vega-lite 绑定文档的说明,有三种可用的绑定类型
点和区间选择可用于数据驱动的交互式元素,例如基于数据中的值进行高亮和筛选。
滑块和复选框可用于逻辑驱动的交互式元素,例如基于这些微件中的绝对值进行高亮和筛选。
区间选择可以绑定到比例尺,例如放大地图。
下表总结了 Vega-Lite 中支持的输入元素
输入元素 |
描述 |
示例 |
---|---|---|
渲染为复选框,允许选择多个项目。 |
||
单选按钮,强制只能选择一个 |
||
下拉框,用于从列表中选择单个项目 |
||
显示为滑块,允许沿比例尺选择。 |
||
支持许多 HTML 输入元素的通用方法 |
微件绑定#
微件是 HTML 输入元素,例如下拉列表、滑块、单选按钮和搜索框。变量和选择参数与微件结合使用有三种策略:数据驱动查找、数据驱动比较和逻辑驱动比较。
数据驱动查找#
数据驱动查找使用微件的活动值以及 selection
参数,在图表的数据集中查找具有匹配值的点。例如,我们可以建立输入微件和点选择之间的绑定,以过滤数据,如下面的示例所示,其中使用下拉列表高亮显示特定 Origin
的汽车
import altair as alt
from vega_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
)
除了上表中列出的微件之外,Altair 还可以通过更通用的 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 我们想要与数据框中的列进行比较,而不是与名为 xval
的 Python 变量进行比较,如果只写 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
来查找精确值,但切换到选择参数并指定字段/编码通常更方便。
逻辑驱动比较#
逻辑比较是一种基于逻辑规则和条件的比较,而不是基于实际数据值本身。例如,对于复选框微件,我们希望检查复选框的状态是 True 还是 False,并根据是否选中它执行某些操作。当我们像这样使用复选框作为切换时,我们需要使用 param 而不是 selection_point,因为我们不想检查数据中是否有 True/False 值,而只是检查复选框的值是 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
)
因为这是一种常见的模式,Altair 提供了 interactive()
方法,可以更简洁地创建比例尺绑定的选择
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N',
).interactive()
编码通道绑定#
要根据微件中的选择更新图表中显示的列,我们需要将微件绑定到编码通道。与图例和比例尺绑定不同,无法在选择初始化时设置与编码通道的绑定(例如,输入 bind='x'
)。相反,可以使用参数将选择的值传递给编码通道。这提供了更大的灵活性,但在解决 vega/vega-lite#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=f'datum[{xcol_param.name}]'
).add_params(
xcol_param
)
在计算转换中使用参数允许我们定义动态计算(例如,减去不同对的列),正如您在交互式列选择图库示例中看到的那样。在该示例中,图表标题也使用表达式中的参数动态更新,这在标题中的内联表达式中有更详细的描述。请注意,目前无法根据选定的参数值动态更改轴标题,但可以使用文本标记代替(如此 SO 答案中所述),直到解决 vega/vega-lite#7264。