分层和多视图图表#
除了基本的 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 的图表网格,展示数据的不同视图。代码是直接的,虽然有点冗长。
可通过 Chart.repeat() 方法访问的 RepeatChart 模式,使这种类型的图表更容易生成:
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 在 y 轴上使用 alt.repeat('layer') 进行分层:
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")
尽管上述每个示例都在列中进行了数据的分面,但也支持在行中(或在行和列中)进行分面。