表达式#
Altair 通过利用 Vega 的表达式语言编写基本公式来实现自定义交互。Vega 表达式字符串是一组定义良好的 JavaScript 风格的操作。为了简化在 Python 中构建这些表达式,Altair 提供了 expr
模块,该模块提供了常量和函数,用于使用 Python 语法构建表达式。Altair 中同时支持 JavaScript 语法和 Python 语法来定义表达式,每种语法都有一个入门示例,可以在 Calculate 转换文档中找到,因此我们建议在继续之前查阅该页面。
参数中的表达式#
在以下示例中,我们定义了一个与名为 param_width
的参数关联的范围。然后,我们通过 param
使用 JavaScript 和 Python 语法分别赋值两个表达式。如前所述,我们通过引用参数名称来访问参数值;在 JavaScript 中通过 f"{param_width.name}"
完成,而在 Python 中只需键入变量名即可。使用这两个在参数中定义的表达式,我们可以将它们连接到编码通道选项,例如轴的标题颜色。如果宽度小于 200
,颜色为 red
;否则,颜色为 blue
。
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' : 'blue'"
,它等价于 Python 函数 expr.if_(param_width < 200, 'red', 'blue')
。定义为参数的表达式也需要在图表中通过 .add_params()
添加。
内联表达式#
除了如上所示在参数定义中赋值表达式外,expr()
工具函数允许我们定义内联表达式。内联表达式不是参数,因此可以直接添加到图表规范中,而不是通过 add_params
添加,这是一种方便的简写方式,避免编写完整的参数代码。
在此示例中,我们修改上面的图表,根据内联表达式改变点的大小。我们没有创建条件语句,而是直接使用表达式的值作为大小,因此只需指定参数的名称。
chart.mark_point(size=alt.expr(param_width.name))
除了修改 mark_*
参数外,内联表达式还可以作为值定义传递给编码通道。在这里,我们通过这种替代方法对图表进行了与上一个示例完全相同的修改
chart.encode(size=alt.value(alt.expr(param_width.name)))
某些参数名称在 Vega-Lite 中具有特殊含义,例如,将参数命名为 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-string 来扩展前一个示例的代码。参数值需要额外的引号和加号才能正确解释。
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 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, 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.regex
定义正则表达式字符串,并使用 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。相当强大!
表达式总结#
Altair 可以利用 Vega 的表达式语言编写基本公式,从而实现自定义交互。
Altair 中支持 JavaScript 风格和 Python 风格的语法来定义表达式。
Altair 提供了
expr
模块,允许使用 Python 语法构建表达式。可以在图表规范中使用两种方法包含表达式:通过
param(expr=...)
参数定义或使用expr(...)
工具函数内联。表达式可用于文档中提及接受 ExprRef 的任何位置。这主要在图表规范内的三个位置:标记属性、编码通道选项以及编码通道的值定义内。它们也支持在图表标题中使用,但尚不支持副标题或引导标题(即坐标轴和图例,详见 vega/vega-lite#7408)。