基本统计可视化#

(本教程改编自 Vega-Lite 的文档

本教程将指导您完成在 Altair 中创建可视化的基本过程。首先,您需要确保已安装 Altair 包及其依赖项(参见 安装)。本教程假定您正在 Jupyter Notebook 用户界面(例如 JupyterLab、Colab 或 VS Code)中工作,以便图表自动渲染。如果您使用其他界面,您可能需要在继续之前阅读关于如何显示 Altair 图表的信息(参见 显示 Altair 图表)。

以下是本基础教程的概要

数据#

Altair 中的数据围绕 pandas Dataframe 构建。统计可视化的一个显著特点是它始于 整洁的 Dataframe。在本教程中,我们将首先导入 pandas 并创建一个简单的 DataFrame 进行可视化,其中列 a 中包含一个类别变量,列 b 中包含一个数值变量

import pandas as pd
data = pd.DataFrame({'a': list('CCCDDDEEE'),
                     'b': [2, 7, 4, 1, 2, 6, 8, 4, 7]})

使用 Altair 时,数据集最常见的是以 Dataframe 的形式提供。正如我们将看到的,Dataframe 的带标签列是使用 Altair 绘图的关键部分。

Chart 对象#

Altair 中的基本对象是 Chart,它将一个 Dataframe 作为单个参数

import altair as alt
chart = alt.Chart(data)

目前,我们已经定义了 Chart 对象,但尚未告诉图表对数据做任何事情。这将在稍后介绍。

编码和标记#

有了这个 Chart 对象,我们现在可以指定我们希望如何可视化数据。这是通过 Chart 对象的 mark 属性完成的,最方便的方法是使用 Chart.mark_* 方法访问。例如,我们可以使用 mark_point() 将数据显示为点

alt.Chart(data).mark_point()

这里的渲染结果是数据集中每行一个点,所有点都绘制在彼此之上,因为我们尚未指定这些点的位置。

为了在视觉上区分这些点,我们可以将各种 编码通道,或简称为 通道,映射到数据集中的列。例如,我们可以使用 x 通道对数据变量 a 进行编码,x 通道表示点的 x 轴位置。这可以通过 Chart.encode() 方法直接完成

alt.Chart(data).mark_point().encode(
    x='a',
)

encode() 方法在编码通道(例如 xycolorshapesize 等)与数据集中的列之间建立键值映射,通过列名访问。

对于 pandas Dataframe,Altair 会自动确定映射列的适当数据类型,在本例中是一个 名义 值,或无序类别。

虽然我们现在已按一个属性区分了数据,但在每个类别中仍然有多个点重叠。让我们通过添加一个 y 编码通道并将其映射到 "b" 列来进一步区分它们

alt.Chart(data).mark_point().encode(
    x='a',
    y='b'
)

Altair 再次自动推断 "b" 列中的数据类型,这次将其视为 定量 类型(即实数值)。此外,我们还看到网格线和适当的坐标轴标题也会自动添加。

数据转换:聚合#

为了在数据可视化方面提供更大的灵活性,Altair 内置了数据 聚合 的语法。例如,我们可以通过在列标识符中指定此聚合来计算所有值的平均值

alt.Chart(data).mark_point().encode(
    x='a',
    y='average(b)'
)

现在,在每个 x 轴类别中,我们看到一个点,反映了该类别中值的平均值。

通常,聚合值不是由点标记表示,而是由条形标记表示。我们可以通过将 mark_point() 替换为 mark_bar() 来实现这一点

alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)'
)

由于类别特征被映射到 x 轴,结果是一个垂直条形图。要获得一个水平条形图,我们只需要交换 xy 关键词

alt.Chart(data).mark_bar().encode(
    y='a',
    x='average(b)'
)

旁白:检查 JSON 输出#

回想一下,Altair 的主要目的是将图表规范转换为符合 Vega-Lite 模式的 JSON 字符串。此处使用 to_json() 方法检查 Altair 导出并作为 JSON 发送给 Vega-Lite 的 JSON 规范是很有启发性的

chart = alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)',
)
print(chart.to_json())
{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.20.1.json",
  "config": {
    "view": {
      "continuousHeight": 300,
      "continuousWidth": 300
    }
  },
  "data": {
    "name": "data-9b610f80003d046838adda5e50d859e9"
  },
  "datasets": {
    "data-9b610f80003d046838adda5e50d859e9": [
      {
        "a": "C",
        "b": 2
      },
      {
        "a": "C",
        "b": 7
      },
      {
        "a": "C",
        "b": 4
      },
      {
        "a": "D",
        "b": 1
      },
      {
        "a": "D",
        "b": 2
      },
      {
        "a": "D",
        "b": 6
      },
      {
        "a": "E",
        "b": 8
      },
      {
        "a": "E",
        "b": 4
      },
      {
        "a": "E",
        "b": 7
      }
    ]
  },
  "encoding": {
    "x": {
      "field": "a",
      "type": "nominal"
    },
    "y": {
      "aggregate": "average",
      "field": "b",
      "type": "quantitative"
    }
  },
  "mark": {
    "type": "bar"
  }
}

请注意,这里的 encode(x='a') 已扩展为一个 JSON 结构,其中包含一个 field 名称和一个 type 数据类型。encode(y='b') 也以类似方式扩展,并包含一个 aggregate 字段。

Altair 的完整简写语法也包含指定列类型的方式

y = alt.Y('average(b):Q')
print(y.to_json())
{
  "aggregate": "average",
  "field": "b",
  "type": "quantitative"
}

这种简写等同于按名称拼出参数

y = alt.Y(field='b', type='quantitative', aggregate='average')
print(y.to_json())

这种更详细的指定通道的方式可以直接在 Altair 图表规范中使用,这在使用一些更高级的字段配置时会很有用

alt.Chart(data).mark_bar().encode(
    alt.Y('a', type='nominal'),
    alt.X('b', type='quantitative', aggregate='average')
)

自定义可视化#

默认情况下,Altair 通过 Vega-Lite 对可视化的默认属性做了一些选择。Altair 还提供了一个 API 来自定义可视化的外观。例如,我们可以使用通道类的 title() 方法指定轴标题,并且可以通过将 Chart.mark_* 方法的 color 关键词设置为任何有效的 HTML 颜色字符串来指定标记的颜色

alt.Chart(data).mark_bar(color='firebrick').encode(
    alt.Y('a').title('category'),
    alt.X('average(b)').title('avg(b) by category')
)

发布可视化#

可视化数据后,您可能想将其发布到网络上。这可以通过使用 Vega-Embed Javascript 包轻松完成。可以使用 Chart.save() 方法为任何图表生成一个简单的独立 HTML 文档示例

chart = alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)',
)
chart.save('chart.html')

基本的 HTML 模板产生的输出如下所示,其中 Chart.to_json() 生成的图表的 JSON 规范应存储在 spec Javascript 变量中

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.jsdelivr.net.cn/npm/vega@3"></script>
    <script src="https://cdn.jsdelivr.net.cn/npm/vega-lite@2"></script>
    <script src="https://cdn.jsdelivr.net.cn/npm/vega-embed@3"></script>
  </head>
  <body>
    <div id="vis"></div>
    <script type="text/javascript">
      var spec = {};  /* JSON dump of your chart's spec */
      var opt = {"renderer": "canvas", "actions": false};  /* Options for the embedding */
      vegaEmbed("#vis", spec, opt);
    </script>
  </body>
</html>

save() 方法提供了一种方便的方式将此类 HTML 输出保存到文件。有关嵌入 Altair/Vega-Lite 的更多信息,请参阅 Vega-Embed 项目的文档。