分层和多视图图表#
除了基本的 Chart
对象外,Altair 还提供了多种复合图表类型,可用于创建堆叠图、分层图、分面图和重复图表。它们总结在下表中
类 |
函数形式 |
运算符形式 |
参考 |
---|---|---|---|
|
|
||
|
|
||
|
|
类 |
方法形式 |
参考 |
---|---|---|
|
||
|
分层图表#
分层图表允许您在同一组坐标轴上叠加两个不同的图表。例如,当您希望为相同数据绘制多个标记时,它们非常有用;例如
import altair as alt
from vega_datasets import data
stocks = data.stocks.url
base = alt.Chart(stocks).encode(
x='date:T',
y='price:Q',
color='symbol:N'
).transform_filter(
alt.datum.symbol == 'GOOG'
)
base.mark_line() + base.mark_point()
这里我们使用了 +
运算符来创建分层图表;或者,我们可以使用 alt.layer
函数,该函数接受任意数量的图表作为其参数
alt.layer(
base.mark_line(),
base.mark_point(),
base.mark_rule()
).interactive()
这两种模式的输出都是一个 LayerChart
对象,它具有类似于 Chart
对象的属性和方法。
图层顺序#
在分层图表中,图层的顺序由它们指定的顺序决定。例如,当使用 layer1 + layer2
或 alt.layer(layer1, layer2)
创建图表时,layer1
将出现在 layer2
下方,并且 layer2
可能会遮挡 layer1
的标记。
例如,考虑下面的图表,我们在热力图的顶部绘制点
import altair as alt
from vega_datasets import data
source = data.movies.url
heatmap = alt.Chart(source).mark_rect().encode(
alt.X('IMDB_Rating:Q').bin(),
alt.Y('Rotten_Tomatoes_Rating:Q').bin(),
alt.Color('count()').scale(scheme='greenblue')
)
points = alt.Chart(source).mark_circle(
color='black',
size=5,
).encode(
x='IMDB_Rating:Q',
y='Rotten_Tomatoes_Rating:Q',
)
heatmap + points
如果我们将两个图层颠倒顺序,则点将先绘制,然后会被热力图标记遮挡
points + heatmap
如果您在创建分层图表时没有看到预期的输出,请确保您正确地对图层进行了排序。
水平串联#
将两个图并排放置通常可以使用 HConcatChart
对象完成,该对象可以使用 hconcat
函数或 |
运算符创建。
例如,这里有一个散点图,它与显示点分布的直方图进行了串联
import altair as alt
from vega_datasets import data
iris = data.iris.url
chart1 = alt.Chart(iris).mark_point().encode(
x='petalLength:Q',
y='petalWidth:Q',
color='species:N'
).properties(
height=300,
width=300
)
chart2 = alt.Chart(iris).mark_bar().encode(
x='count()',
y=alt.Y('petalWidth:Q').bin(maxbins=30),
color='species:N'
).properties(
height=300,
width=100
)
chart1 | chart2
本例使用了 |
运算符,但也可以类似地使用 hconcat()
函数创建
alt.hconcat(chart1, chart2)
这两种模式的输出都是一个 HConcatChart
对象,它具有许多与 Chart
对象相同的顶层方法和属性。
最后,请记住,对于某些类型的水平串联图表,其中每个面板只修改可视化效果的一个方面,重复图表和分面图表更方便(更多解释请参见重复图表和分面图表)。
垂直串联#
与上面的水平串联类似,Altair 通过 vconcat()
函数或 &
运算符提供垂直串联。
例如,这里我们将同一数据的两个视图垂直串联起来,并使用 brush
选择来添加交互性
import altair as alt
from vega_datasets import data
source = data.sp500.url
brush = alt.selection_interval(encodings=['x'])
base = alt.Chart(source).mark_area().encode(
x = 'date:T',
y = 'price:Q'
).properties(
width=600,
height=200
)
upper = base.encode(alt.X('date:T').scale(domain=brush))
lower = base.properties(
height=60
).add_params(brush)
alt.vconcat(upper, lower)
请注意,我们也可以使用 upper & lower
,而不是更冗长的 alt.vconcat(upper, lower)
。
重复图表#
RepeatChart
对象为特定类型的水平或垂直串联提供了一个方便的接口,其中串联面板之间唯一的区别是修改了一个或多个编码。
例如,假设您想创建一个多面板散点图来显示多维数据集的不同投影。让我们先使用 hconcat
和 vconcat
手动创建这样的图表,然后再展示如何使用 repeat
更有效地构建图表
import altair as alt
from vega_datasets import data
iris = data.iris.url
base = alt.Chart().mark_point().encode(
color='species:N'
).properties(
width=200,
height=200
).interactive()
chart = alt.vconcat(data=iris)
for y_encoding in ['petalLength:Q', 'petalWidth:Q']:
row = alt.hconcat()
for x_encoding in ['sepalLength:Q', 'sepalWidth:Q']:
row |= base.encode(x=x_encoding, y=y_encoding)
chart &= row
chart
在本例中,我们显式循环遍历不同的 x 和 y 编码,以创建显示数据不同视图的 2 x 2 网格图表。代码很直观,虽然有点冗长。
RepeatChart
模式通过 Chart.repeat()
方法访问,使这类图表更容易生成
import altair as alt
from vega_datasets import data
iris = data.iris.url
alt.Chart(iris).mark_point().encode(
alt.X(alt.repeat("column"), type='quantitative'),
alt.Y(alt.repeat("row"), type='quantitative'),
color='species:N'
).properties(
width=200,
height=200
).repeat(
row=['petalLength', 'petalWidth'],
column=['sepalLength', 'sepalWidth']
).interactive()
这里的关键是 Chart.repeat()
方法:它允许您为行和/或列指定一组编码,这些编码可以在图表的编码规范中使用 alt.repeat('row')
或 alt.repeat('column')
来引用。
使用 repeat
方法的另一种选择是用于分层。在这里,US_Gross
和 Worldwide_Gross
列使用 alt.repeat('layer')
在 y
轴上分层显示
import altair as alt
from vega_datasets import data
source = data.movies()
alt.Chart(source).mark_line().encode(
x=alt.X("IMDB_Rating").bin(),
y=alt.Y(alt.repeat('layer')).aggregate('mean').title("Mean of US and Worldwide Gross"),
color=alt.ColorDatum(alt.repeat('layer'))
).repeat(layer=["US_Gross", "Worldwide_Gross"])
目前 repeat
只能是编码(例如,不能是数据转换),但 Vega-Lite 社区正在讨论未来使这种模式更通用。
分面图表#
与重复图表一样,分面图表提供了数据集的多个视图。但不同之处在于,它不是为不同的编码设置不同的面板,而是为不同的数据子集设置不同的面板。例如,鸢尾花数据集中每种花都对应一个面板。
这也被称为 小型倍数图、棚架图、格状图、网格图或面板图。
我们可以通过结合过滤转换和水平串联来手动实现这一点
import altair as alt
from vega_datasets import data
iris = data.iris.url
base = alt.Chart(iris).mark_point().encode(
x='petalLength:Q',
y='petalWidth:Q',
color='species:N'
).properties(
width=160,
height=160
)
chart = alt.hconcat()
for species in ['setosa', 'versicolor', 'virginica']:
chart |= base.transform_filter(alt.datum.species == species)
chart
与重复图表的手动方法一样,这很直接,虽然有点冗长。
使用 .facet
会更简洁一些
alt.Chart(iris).mark_point().encode(
x='petalLength:Q',
y='petalWidth:Q',
color='species:N'
).properties(
width=180,
height=180
).facet(
column='species:N'
)
对于这类简单图表,还有一个 column
编码通道可以获得相同的结果
alt.Chart(iris).mark_point().encode(
x='petalLength:Q',
y='petalWidth:Q',
color='species:N',
column='species:N'
).properties(
width=180,
height=180
)
使用 .facet
的优点在于它可以创建更复杂的复合图表的分面视图。例如,这是一个带有悬停选择的分层图表的分面视图
hover = alt.selection_point(on='pointerover', nearest=True, empty=False)
when_hover = alt.when(hover)
base = alt.Chart(iris).encode(
x='petalLength:Q',
y='petalWidth:Q',
color=when_hover.then("species:N").otherwise(alt.value("lightgray"))
).properties(
width=180,
height=180,
)
points = base.mark_point().add_params(hover)
text = base.mark_text(dy=-5).encode(
text="species:N",
opacity=when_hover.then(alt.value(1)).otherwise(alt.value(0)),
)
(points + text).facet("species:N")
尽管上面的每个示例都按列对数据进行了分面,但也支持按行(或按行和列)进行分面。