自定义可视化#

Altair的目标是自动选择有用的绘图设置和配置,以便用户可以专注于数据,而不是绘图的机制。也就是说,一旦你有了有用的可视化,通常会想要调整其中某些方面。本节文档概述了一些进行这些调整的方法。

全局配置 vs. 本地配置 vs. 编码#

根据情况,通常有两到三种不同的方法来指定图表的外观。
例如,假设我们正在创建一个 cars 数据集的散点图:

import altair as alt
from vega_datasets import data
cars = data.cars.url

alt.Chart(cars).mark_point().encode(
    x='Acceleration:Q',
    y='Horsepower:Q'
)

假设您希望将点的颜色更改为红色,并将点的透明度设置为20%。对此有三种可能的方法:

  1. “全局配置”作用于整个图表对象

  2. “本地配置”作用于图表的一个标记

  3. “编码”通道也可以用来设置一些图表属性

全局配置#

首先,所有图表类型在顶层都有一个 "config" 属性,作为整个图表及其子图表的主题。在这里,您可以指定轴属性、标记属性、选择属性等内容。

Altair 允许您通过图表的 configure_* 方法访问这些。这里我们将使用 configure_mark() 属性:

alt.Chart(cars).mark_point().encode(
    x='Acceleration:Q',
    y='Horsepower:Q'
).configure_mark(
    opacity=0.2,
    color='red'
)

使用这种全局配置时,有几点需要注意:

  1. 根据设计,配置将影响图表中使用的每个标记

  2. 全局配置仅在顶层允许;例如,如果您尝试将上述图表与其他图表叠加,将会导致错误。

有关全局配置选项的完整讨论,请参见 顶级图表配置

本地配置#

如果您希望本地配置标记的外观,使得该设置仅影响您引用的特定图表属性,可以通过本地配置设置来实现。

在标记属性的情况下,最佳方法是将属性设置为mark_*方法的参数。这里我们将使用mark_point()

alt.Chart(cars).mark_point(opacity=0.2, color='red').encode(
    x='Acceleration:Q',
    y='Horsepower:Q'
)

与使用全局配置时不同,在这里可以将生成的图表作为复合图表中的图层或面。

像这样的本地配置设置将始终覆盖全局设置。

编码#

最后,可以通过编码通道设置图表属性(参见 编码)。您可以直接将属性映射到值,而不是将属性映射到数据列,使用 value() 函数:

alt.Chart(cars).mark_point().encode(
    x='Acceleration:Q',
    y='Horsepower:Q',
    opacity=alt.value(0.2),
    color=alt.value('red')
)

请注意,只有有限的一组标记属性可以绑定到编码,因此对于某些属性(例如 fillOpacitystrokeOpacity 等),编码方法不可用。

编码设置将始终覆盖本地或全局配置设置。

选择哪个?#

这三种方法的优先级顺序是(从最低到最高)全局配置本地配置编码。也就是说,如果图表属性在全局和本地都被设置,本地设置将优先。如果属性既通过配置设置,又通过编码设置,编码将优先。

在大多数情况下,我们建议始终使用最高优先级的方式来设置属性;即编码,或用于未与编码绑定的属性的本地配置。全局配置应保留用于创建在图表渲染之前应用的主题。

调整标题#

默认情况下,Altair 图表没有标题,如此示例所示。

import altair as alt
from vega_datasets import data

iowa = data.iowa_electricity.url

alt.Chart(iowa).mark_area().encode(
    x="year:T",
    y=alt.Y("net_generation:Q").stack("normalize"),
    color="source:N"
)

您可以通过将title关键字参数与数据一起传递来添加简单的标题。

alt.Chart(iowa, title="Iowa's green energy boom").mark_area().encode(
    x="year:T",
    y=alt.Y("net_generation:Q").stack("normalize"),
    color="source:N"
)

通过传递一个 alt.Title 对象,也可以添加一个副标题。

alt.Chart(
   iowa,
   title=alt.Title(
       "Iowa's green energy boom",
       subtitle="A growing share of the state's energy has come from renewable sources"
   )
).mark_area().encode(
    x="year:T",
    y=alt.Y("net_generation:Q").stack("normalize"),
    color="source:N"
)

副标题可以延伸到两行,通过传递一个列表,其中每个列表项是一行(如果您不想像下面的示例那样手动创建这个列表,您可以使用 wrap 函数来自 textwrap library 将字符串拆分为一定长度的子字符串列表)。

alt.Chart(
   iowa,
   title=alt.Title(
       "Iowa's green energy boom",
       subtitle=["A growing share of the state's energy", "has come from renewable sources"]
   )
).mark_area().encode(
    x="year:T",
    y=alt.Y("net_generation:Q").stack("normalize"),
    color="source:N"
)

这个 Title 对象还可以配置其他许多属性,例如,将其 anchor 固定在图表的 'start'(左侧),并将其 orient 放置在图表的 'bottom'(底部)(请参见 Top-Level Chart Configuration 获取更多选项)。

alt.Chart(
   iowa,
   title=alt.Title(
       "Iowa's green energy boom",
       subtitle="A growing share of the state's energy has come from renewable sources",
       anchor='start',
       orient='bottom',
       offset=20
   )
).mark_area().encode(
    x="year:T",
    y=alt.Y("net_generation:Q").stack("normalize"),
    color="source:N"
)

在上面的图表中,您可以看到标题完全位于左侧,以便与y轴上的标签对齐。您可以通过将锚点位置的参考 frame 设置为相对于 'group'(即图表的数据部分,排除标签和标题)来将标题与轴线对齐。

alt.Chart(
   iowa,
   title=alt.Title(
       "Iowa's green energy boom",
       subtitle=["A growing share of the state's energy has come from", "renewable sources"],
       anchor='start',
       frame='group',
       orient='bottom',
       offset=20
   )
).mark_area().encode(
    x="year:T",
    y=alt.Y("net_generation:Q").stack("normalize"),
    color="source:N"
)

调整轴限#

Altair使用的默认坐标轴限制取决于数据的类型。 要超越这些默认值微调坐标轴限制,可以使用 scale()方法进行坐标轴编码。例如,考虑以下图表:

import altair as alt
from vega_datasets import data

cars = data.cars.url

alt.Chart(cars).mark_point().encode(
    x='Acceleration:Q',
    y='Horsepower:Q'
)

Altair 继承了 Vega-Lite 的惯例,即在定量轴上始终包含零点;如果您想要关闭此功能,可以将 scale() 方法添加到 X 编码中,以指定 zero=False

alt.Chart(cars).mark_point().encode(
    alt.X('Acceleration:Q').scale(zero=False),
    y='Horsepower:Q'
)

要指定确切的轴限制,您可以使用 domain 属性:

alt.Chart(cars).mark_point().encode(
    alt.X('Acceleration:Q').scale(domain=(5, 20)),
    y='Horsepower:Q'
)

问题是数据仍然存在于刻度之外,我们需要告诉 Altair 如何处理这些数据。一个选择是通过将 "clip" 属性设置为 True 来“剪切”数据:

alt.Chart(cars).mark_point(clip=True).encode(
    alt.X('Acceleration:Q').scale(domain=(5, 20)),
    y='Horsepower:Q'
)

另一个选项是“限制”数据;也就是说,将超出限制的点移动到域的边缘:

alt.Chart(cars).mark_point().encode(
    alt.X('Acceleration:Q').scale(domain=(5, 20), clamp=True),
    y='Horsepower:Q'
).interactive()

对于像上面这样的互动图表,钳制是动态发生的,这在你平移和缩放图表时,考虑到异常值是很有用的。

调整坐标轴标签#

Altair 还为您提供了轻松配置轴标签外观的工具。
例如,考虑这个图表:

import pandas as pd
df = pd.DataFrame(
    {'x': [0.03, 0.04, 0.05, 0.12, 0.07, 0.15],
    'y': [10, 35, 39, 50, 24, 35]
})

alt.Chart(df).mark_circle().encode(
    x='x',
    y='y'
)

为了微调刻度标签的格式并为每个轴添加自定义标题,我们可以在axis()方法中将自定义轴定义传递给XY编码。以下是将x标签格式化为百分比以及将y标签格式化为美元值的示例:

alt.Chart(df).mark_circle().encode(
    alt.X('x').axis(format='%').title('percentage'),
    alt.Y('y').axis(format='$').title('dollar amount')
)

轴标签可以被轻松移除:

alt.Chart(df).mark_circle().encode(
    alt.X('x').axis(labels=False),
    alt.Y('y').axis(labels=False)
)

轴标题也可以旋转:

alt.Chart(df).mark_circle().encode(
    alt.X('x').axis(title="x"),
    alt.Y('y').axis(
        title="Y Axis Title",
        titleAngle=0,
        titleAlign="left",
        titleY=-2,
        titleX=0,
    )
)

还有其他格式代码可用;有关这些代码的列表,请参阅d3格式代码文档

调整图例#

当将 colorshapesize 参数传递给 encode() 函数时,图表会自动添加图例。我们将在这个例子中使用 color

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    x='petalWidth',
    y='petalLength',
    color='species'
)

在这种情况下,图例可以通过引入 Color 类进行自定义,并利用其 legend() 方法。shapesize 参数各自有相应的类。

所有这些的图例选项都期望一个 Legend 对象作为其输入,该对象接受参数以自定义其外观的许多方面。一个例子是使用 orient 参数将图例移动到另一个位置。

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    x='petalWidth',
    y='petalLength',
    color=alt.Color('species').legend(orient="left")
)

您可以做的另一件事是设置一个 title;在这种情况下,我们可以直接使用 title() 方法作为快捷方式或者在 legend() 方法内部指定 title 参数:。

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    x='petalWidth',
    y='petalLength',
    color=alt.Color('species').title("Species by color")
)

您可以通过提交一个空值来完全删除图例。

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    x='petalWidth',
    y='petalLength',
    color=alt.Color('species').legend(None),
)

移除图表边框#

基本的Altair图表绘制时都有网格和外部边框。 要创建一个没有边框的图表,您需要同时移除这两个部分。

作为一个例子,让我们从一个简单的散点图开始。

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    x='petalWidth',
    y='petalLength',
    color='species'
)

首先使用 configure_axis() 方法移除网格。

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    x='petalWidth',
    y='petalLength',
    color='species'
).configure_axis(
    grid=False
)

您会注意到,尽管内部规则已消失,外部边框仍然存在。通过在 configure_view() 内部设置 stroke=None 来隐藏它(strokeWidth=0strokeOpacity=0 也有效):

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    x='petalWidth',
    y='petalLength',
    color='species'
).configure_axis(
    grid=False
).configure_view(
    stroke=None
)

还可以通过将上述选项与在编码时将 axis 设置为 None 结合来完全去除所有边框和轴。

import altair as alt
from vega_datasets import data

iris = data.iris()

alt.Chart(iris).mark_point().encode(
    alt.X('petalWidth').axis(None),
    alt.Y('petalLength').axis(None),
    color='species'
).configure_axis(
    grid=False
).configure_view(
    stroke=None
)

自定义颜色#

如在 数据类型对颜色尺度的影响 中讨论的,Altair 根据颜色编码的数据类型选择合适的默认颜色方案。这些默认值可以使用 scale() 方法进行自定义,属于 Color 类。

配色方案#

Altair 包含了一组为类别型和序列型数据定义的命名颜色方案,由 vega 项目定义;有关可用颜色方案的完整图库,请参见 Vega documentation。这些方案可以传递给 scheme 参数的 scale() 方法:

import altair as alt
from vega_datasets import data

cars = data.cars()

alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color=alt.Color('Acceleration').scale(scheme="lightgreyred")
)

我们上面使用的配色方案突出了尺度一端的点,同时保持其余部分低调。如果我们想将较低的 Acceleration 数据高亮为红色,可以使用 reverse 参数来反转配色方案:

alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color=alt.Color('Acceleration').scale(scheme="lightgreyred", reverse=True)
)

颜色域和范围#

要创建自定义颜色尺度,我们可以使用 domainrange 参数,分别用于 scale 方法中的值和颜色。这对于连续尺度也有效,可以帮助突出特定范围的值:

domain = [5, 8, 10, 12, 25]
range_ = ['#9cc8e2', '#9cc8e2', 'red', '#5ba3cf', '#125ca4']

alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color=alt.Color('Acceleration').scale(domain=domain, range=range_)
)

对于离散刻度:

domain = ['Europe', "Japan", "USA"]
range_ = ['seagreen', 'firebrick', 'rebeccapurple']

alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color=alt.Color('Origin').scale(domain=domain, range=range_)
)

原始颜色值#

scale 是将原始输入值映射为适当颜色编码以显示数据的内容。如果您的数据条目包含原始颜色名称或代码,您可以设置 scale(None) 以直接使用这些颜色:

import pandas as pd
import altair as alt

data = pd.DataFrame({
    'x': range(6),
    'color': ['red', 'steelblue', 'chartreuse', '#F4D03F', '#D35400', '#7D3C98']
})

alt.Chart(data).mark_point(
    filled=True,
    size=100
).encode(
    x='x',
    color=alt.Color('color').scale(None)
)

调整条形标记的宽度#

条形图中条形的宽度通过 size 属性在 mark_bar() 中进行控制:

import altair as alt
import pandas as pd

data = pd.DataFrame({'name': ['a', 'b'], 'value': [4, 10]})

alt.Chart(data).mark_bar(size=10).encode(
    x='name:O',
    y='value:Q'
)

但是由于 mark_bar(size=10) 只控制条形的宽度,因此图表的宽度可能无法相应调整:

alt.Chart(data).mark_bar(size=30).encode(
    x='name:O',
    y='value:Q'
)

因此,通常更倾向于根据不同类别的数量来设置整个图表的宽度,使用 Step,你可以在下面的几个图表中看到一个示例。

调整图表大小#

图表的大小可以使用 widthheight 属性进行调整。
例如:

import altair as alt
from vega_datasets import data

cars = data.cars()

alt.Chart(cars).mark_bar().encode(
    x='Origin',
    y='count()'
).properties(
    width=200,
    height=150
)

请注意,在分面或其他复合图表的情况下,这个宽度和高度适用于子图而不是整体图表:

alt.Chart(cars).mark_bar().encode(
    x='Origin',
    y='count()',
    column='Cylinders:Q'
).properties(
    width=100,
    height=100
).resolve_scale(
    x='independent'
)

要根据不同类别的数量更改图表大小,您可以使用Step类为每个类别指定宽度/高度,而不是为整个图表指定:

alt.Chart(cars).mark_bar().encode(
    x='Origin',
    y='count()',
    column='Cylinders:Q'
).properties(
    width=alt.Step(35),
    height=100
).resolve_scale(
    x='independent'
)

如果您希望您的图表大小能够响应其呈现的HTML页面或容器的宽度,您可以将 widthheight 设置为字符串 "container"

alt.Chart(cars).mark_bar().encode(
    x='Origin',
    y='count()',
).properties(
    width='container',
    height=200
)

注意,只有当其父元素的大小在图表自身之外确定时,这个内容才会随着容器缩放;例如,容器可能是一个

元素,具有样式 width: 100%; height: 300px.

图表主题#

注意

此材料在 Altair 5.5.0 发布时发生了显著变化。

Altair 提供了一个主题注册表,使用户能够在任何 Python 会话中全局应用图表配置。altair.theme 模块提供了 辅助函数 来与注册表进行交互。

注册表中的每个主题都是一个函数,定义一个规范字典,该字典将会添加到每个创建的图表中。 例如,默认主题配置了单个图表的默认大小:

>>> import altair as alt
>>> default = alt.theme.get()
>>> default()
{'config': {'view': {'continuousWidth': 300, 'continuousHeight': 300}}}

您可以看到,您创建的任何图表都将应用此主题,并将这些配置添加到其规范中:

import altair as alt
from vega_datasets import data

chart = alt.Chart(data.cars.url).mark_point().encode(
    x='Horsepower:Q',
    y='Miles_per_Gallon:Q'
)

chart.to_dict()
    {'config': {'view': {'continuousWidth': 300, 'continuousHeight': 300}}, 'data': {'url': 'https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/cars.json'}, 'mark': {'type': 'point'}, 'encoding': {'x': {'field': 'Horsepower', 'type': 'quantitative'}, 'y': {'field': 'Miles_per_Gallon', 'type': 'quantitative'}}, '$schema': 'https://vega.github.io/schema/vega-lite/v5.20.1.json'}

渲染的图表将反映这些配置:

chart

更改主题#

如果你想在 Python 会话期间启用其他任何主题,你可以调用 altair.theme.enable()。例如,Altair 包含一个主题,其中图表背景是不透明的,而不是透明的:

alt.theme.enable('opaque')
chart.to_dict()
    {'config': {'background': 'white', 'view': {'continuousWidth': 300, 'continuousHeight': 300}}, 'data': {'url': 'https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/cars.json'}, 'mark': {'type': 'point'}, 'encoding': {'x': {'field': 'Horsepower', 'type': 'quantitative'}, 'y': {'field': 'Miles_per_Gallon', 'type': 'quantitative'}}, '$schema': 'https://vega.github.io/schema/vega-lite/v5.20.1.json'}
chart

请注意,图表的背景颜色现在设置为白色。 如果您希望图表不应用任何主题,可以使用名为 'none' 的主题:

alt.theme.enable('none')
chart.to_dict()
    {'data': {'url': 'https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/cars.json'}, 'mark': {'type': 'point'}, 'encoding': {'x': {'field': 'Horsepower', 'type': 'quantitative'}, 'y': {'field': 'Miles_per_Gallon', 'type': 'quantitative'}}, '$schema': 'https://vega.github.io/schema/vega-lite/v5.20.1.json'}
chart

因为视图配置未设置,图表比默认渲染小。

如果您只想为单个图表使用任何主题,可以使用 with 语句来启用临时主题:

with alt.theme.enable('default'):
    spec = chart.to_json()

注意

上述要求在 with 块中执行转换/保存操作,例如 to_dict()to_json()save()。请参见 vega/altair#3586

内置主题#

目前 Altair 并没有提供很多内置主题,但我们计划在未来增加更多选项。

您可以通过下面的 Vega-Altair 主题测试 感受来自 Vega Themes 的主题:

Show Vega-Altair Theme Test

loading...

定义自定义主题#

主题只是一个函数,它返回一个默认值的字典,这些值将在渲染时添加到图表规范中。

使用 altair.theme.register(),我们可以在函数定义的位置注册并启用主题。

例如,在这里我们定义一个主题,其中所有标记都用黑色填充,除非另有说明:

import altair as alt
from vega_datasets import data

# define, register and enable theme

@alt.theme.register("black_marks", enable=True)
def black_marks() -> alt.theme.ThemeConfig:
    return {
        "config": {
            "view": {"continuousWidth": 300, "continuousHeight": 300},
            "mark": {"color": "black", "fill": "black"},
        }
    }


# draw the chart
cars = data.cars.url
alt.Chart(cars).mark_point().encode(
    x='Horsepower:Q',
    y='Miles_per_Gallon:Q'
)

如果您想恢复默认主题,请使用:

alt.themes.enable('default')

在尝试您的主题时,您可以使用以下代码查看它在一系列图表/标记中的效果:

Show Vega-Altair Theme Test code
import altair as alt

VEGA_DATASETS = "https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/"
us_10m = f"{VEGA_DATASETS}us-10m.json"
unemployment = f"{VEGA_DATASETS}unemployment.tsv"
movies = f"{VEGA_DATASETS}movies.json"
barley = f"{VEGA_DATASETS}barley.json"
iowa_electricity = f"{VEGA_DATASETS}iowa-electricity.csv"
common_data = alt.InlineData(
    [
        {"Index": 1, "Value": 28, "Position": 1, "Category": "A"},
        {"Index": 2, "Value": 55, "Position": 2, "Category": "A"},
        {"Index": 3, "Value": 43, "Position": 3, "Category": "A"},
        {"Index": 4, "Value": 91, "Position": 4, "Category": "A"},
        {"Index": 5, "Value": 81, "Position": 5, "Category": "A"},
        {"Index": 6, "Value": 53, "Position": 6, "Category": "A"},
        {"Index": 7, "Value": 19, "Position": 1, "Category": "B"},
        {"Index": 8, "Value": 87, "Position": 2, "Category": "B"},
        {"Index": 9, "Value": 52, "Position": 3, "Category": "B"},
        {"Index": 10, "Value": 48, "Position": 4, "Category": "B"},
        {"Index": 11, "Value": 24, "Position": 5, "Category": "B"},
        {"Index": 12, "Value": 49, "Position": 6, "Category": "B"},
        {"Index": 13, "Value": 87, "Position": 1, "Category": "C"},
        {"Index": 14, "Value": 66, "Position": 2, "Category": "C"},
        {"Index": 15, "Value": 17, "Position": 3, "Category": "C"},
        {"Index": 16, "Value": 27, "Position": 4, "Category": "C"},
        {"Index": 17, "Value": 68, "Position": 5, "Category": "C"},
        {"Index": 18, "Value": 16, "Position": 6, "Category": "C"},
    ]
)
HEIGHT_SMALL = 140
STANDARD = 180
WIDTH_GEO = int(STANDARD * 1.667)
bar = (
    alt.Chart(common_data, height=HEIGHT_SMALL, width=STANDARD, title="Bar")
    .mark_bar()
    .encode(x=alt.X("Index:O").axis(offset=1), y=alt.Y("Value:Q"), tooltip="Value:Q")
    .transform_filter(alt.datum["Index"] <= 9)
)
line = (
    alt.Chart(common_data, height=HEIGHT_SMALL, width=STANDARD, title="Line")
    .mark_line()
    .encode(
        x=alt.X("Position:O").axis(grid=False),
        y=alt.Y("Value:Q").axis(grid=False),
        color=alt.Color("Category:N").legend(None),
        tooltip=["Index:O", "Value:Q", "Position:O", "Category:N"],
    )
)
point_shape = (
    alt.Chart(common_data, height=HEIGHT_SMALL, width=STANDARD, title="Point (Shape)")
    .mark_point()
    .encode(
        x=alt.X("Position:O").axis(grid=False),
        y=alt.Y("Value:Q").axis(grid=False),
        shape=alt.Shape("Category:N").legend(None),
        color=alt.Color("Category:N").legend(None),
        tooltip=["Index:O", "Value:Q", "Position:O", "Category:N"],
    )
)
point = (
    alt.Chart(movies, height=STANDARD, width=STANDARD, title="Point")
    .mark_point(tooltip=True)
    .transform_filter(alt.datum["IMDB_Rating"] != None)
    .transform_filter(
        alt.FieldRangePredicate("Release_Date", [None, 2019], timeUnit="year")
    )
    .transform_joinaggregate(Average_Rating="mean(IMDB_Rating)")
    .transform_calculate(
        Rating_Delta=alt.datum["IMDB_Rating"] - alt.datum.Average_Rating
    )
    .encode(
        x=alt.X("Release_Date:T").title("Release Date"),
        y=alt.Y("Rating_Delta:Q").title("Rating Delta"),
        color=alt.Color("Rating_Delta:Q").title("Rating Delta").scale(domainMid=0),
    )
)
bar_stack = (
    alt.Chart(barley, height=STANDARD, width=STANDARD, title="Bar (Stacked)")
    .mark_bar(tooltip=True)
    .encode(
        x="sum(yield):Q",
        y=alt.Y("variety:N"),
        color=alt.Color("site:N").legend(orient="bottom", columns=2),
    )
)
area = (
    alt.Chart(iowa_electricity, height=STANDARD, width=STANDARD, title="Area")
    .mark_area(tooltip=True)
    .encode(
        x=alt.X("year:T").title("Year"),
        y=alt.Y("net_generation:Q")
        .title("Share of net generation")
        .stack("normalize")
        .axis(format=".0%"),
        color=alt.Color("source:N")
        .title("Electricity source")
        .legend(orient="bottom", columns=2),
    )
)
geoshape = (
    alt.Chart(
        alt.topo_feature(us_10m, "counties"),
        height=STANDARD,
        width=WIDTH_GEO,
        title=alt.Title("Geoshape", subtitle="Unemployment rate per county"),
    )
    .mark_geoshape(tooltip=True)
    .encode(color="rate:Q")
    .transform_lookup("id", alt.LookupData(alt.UrlData(unemployment), "id", ["rate"]))
    .project(type="albersUsa")
)
compound_chart = (
    (bar | line | point_shape) & (point | bar_stack) & (area | geoshape)
).properties(
    title=alt.Title(
        "Vega-Altair Theme Test",
        fontSize=20,
        subtitle="Adapted from https://vega.github.io/vega-themes/",
    )
)

compound_chart

有关主题的更多想法,请参阅Vega Themes仓库。

本地化#

数字、日期和货币的首选格式因语言和地区而异。 Vega-Altair 利用 D3的本地化支持 来简化使用全局 alt.renderers.set_embed_options 函数配置图表的区域设置。

这里 format_localetime_format_locale 可以是 D3 格式字典,或包含预定义区域名称的字符串。例如,这里我们使用意大利区域(名为 it-IT)来处理货币和日期:

import altair as alt
from vega_datasets import data

alt.renderers.set_embed_options(format_locale="it-IT", time_format_locale="it-IT")

source = data.stocks.url
chart = alt.Chart(source).mark_area().transform_filter('year(datum.date) == 2009').encode(
    x='date:T',
    y=alt.Y('price:Q', axis=alt.Axis(format="$.0f")),
    color='symbol:N'
)
chart
Area chart of stock prices using Italian locale

请参阅 https://unpkg.com/d3-format/locale/ 以获取可用格式区域名称的列表,并请参阅 https://unpkg.com/d3-time-format/locale/ 以获取可用时间格式区域的列表。

配置的本地化设置在保存时会持续有效。

注意

全局定义的属性,format_localetime_format_locale,适用于整个会话,而不是特定于单个图表。要将本地化设置恢复为默认的美国英语区域设置,请使用以下命令:

alt.renderers.set_embed_options(format_locale="en-US", time_format_locale="en-US")