使用 Altair 在 Python 中进行简洁的数据绘图

Altair 在 Python 库中提供了一个优雅的界面及其自身的绘图语言
75 位读者喜欢这篇文章。
metrics and data shown on a computer screen

Opensource.com

Python 中可用的绘图库提供了多种呈现数据的方式,您可以根据自己的偏好选择灵活性、设计、易用性或特定风格。

Altair 中的绘图提供了与其他库不同的解决方案,我发现这种方案更简单,因为绘图量是可扩展的。它具有优雅的界面,这要归功于 Vega,这是一种声明式绘图语言,它允许您定义绘图的外观,而不是编写循环和条件语句来构建它们。

精通绘图

我通过绘制相同的多条形图来比较每个 Python 绘图库。在我们进一步深入之前,请注意您可能需要调整您的 Python 环境以运行此代码,包括以下内容。

  • 安装最新版本的 Python(LinuxMacWindows 的说明)
  • 验证 Python 版本是否与教程中使用的库兼容

数据可在线获取,可以使用 pandas 导入

import pandas as pd
df = pd.read_csv('https://anvil.works/blog/img/plotting-in-python/uk-election-results.csv') 

现在我们准备好了。作为比较,这是我们在 Matplotlib 中制作的图表

Matplotlib UK election results

英国选举结果的 Matplotlib 图表(© 2020 Anvil

Matplotlib 图表用了 16 行代码来创建,包括手动计算每个条形的位置。

以下是如何在 Altair 中制作类似图表的方法

    import altair as alt

    chart = alt.Chart(df).mark_bar().encode(
        x='party',
        y='seats',
        column='year',
        color='party',
    )

    chart.save('altair-elections.html')

更加简洁!就像 Seaborn 一样,Altair 可以处理每列一个变量的数据(长格式)。这允许您将每个变量映射到图表的某个方面——Altair 将这些方面称为“通道”。在我们的例子中,我们希望 x 轴上每个 party 有一个条形,y 轴上是每个政党赢得的 seats,并且我们希望按 year 将条形分组到 column 中。我们还希望按 party 对条形进行 color 着色。这就是您在文字中描述它的方式,而且这正是代码所说的!

这是图表的样子

Altair plot with default styling

具有默认样式的 Altair 图表(© 2020 Anvil

调整样式

这与我们想要的相差不远。与 Matplotlib 图表的主要区别在于,每个 Altair year 组之间都显示了一些空白——这只是 Altair 多条形图的一个特性,而不是问题。

但是,我们确实希望进行一些其他的细微样式改进。

非整数值

两个非整数年份名称(Feb 1974Oct 1974)显示为 NaN。我们可以通过将 year 值转换为字符串来修复这些问题

    df['year'] = df['year'].astype(str)

指定排序顺序

然后我们还需要告诉 Altair 如何对数据进行排序。Altair 允许我们通过传递 Column 对象来指定有关 column 通道的更多详细信息。因此,我们告诉它按照数据在 DataFrame 中出现的顺序进行排序

    chart = alt.Chart(df).mark_bar().encode(
        # ...
        column=alt.Column('year', sort=list(df['year']), title=None),
        # ...
    )

删除轴标题

我们通过设置 title=None 从图表顶部删除了“year”标签。我们还要从每列中删除“party”标签

    chart = alt.Chart(df).mark_bar().encode(
        x=alt.X('party', title=None),
        # ...
    )

指定颜色映射

最后,我们希望指定我们自己的颜色用于条形。Altair 允许我们指定 domain 中的值和 range 中的颜色之间的映射,这正是我们需要的

    cmap = {
        'Conservative': '#0343df',
        'Labour': '#e50000',
        'Liberal': '#ffff14',
        'Others': '#929591',
    }

    chart = alt.Chart(df).mark_bar().encode(
        # ...
        color=alt.Color('party', scale=alt.Scale(domain=list(cmap.keys()), range=list(cmap.values())))
    )

带有样式调整的最终代码

应用这些样式调整后,我们的代码在视觉上略微逊色,但它仍然使用了使 Altair 如此可扩展的声明式方法。我们仍然将来自数据的独立变量分配给绘图的不同方面,而不是像我们在 Matplotlib 中经常需要做的那样执行复杂的数据操作。唯一的区别是我们的变量名现在被包装在诸如 alt.X() 之类的对象中,这些对象允许我们调整它们的外观

    import altair as alt
    from votes import long as df

    cmap = {
        'Conservative': '#0343df',
        'Labour': '#e50000',
        'Liberal': '#ffff14',
        'Others': '#929591',
    }

    df['year'] = df['year'].astype(str)

    # We're still assigning, e.g. 'party' to x, but now we've wrapped it 
    # in alt.X in order to specify its styling
    chart = alt.Chart(df).mark_bar().encode(
        x=alt.X('party', title=None),
        y='seats',
        column=alt.Column('year', sort=list(df['year']), title=None),
        color=alt.Color('party', scale=alt.Scale(domain=list(cmap.keys()), range=list(cmap.values())))
    )

    chart.save('altair-elections.html')

公平地说,我们现在已经达到了与我们在 Matplotlib 中使用的代码行数相同的数量 (16)!

这是应用了我们的样式调整的 Altair 图表

The Altair plot with our custom styling

具有自定义样式的 Altair 图表(© 2020 Anvil

结论 

虽然使用 Altair 绘图所需的代码量与其他库类似,但其声明式绘图语言增加了一层我逐渐欣赏的复杂性。Altair 还提供了一种干净地分离的方式来调整和修改样式,这使得语法远离用于绘图的代码块。当考虑 Python 的绘图解决方案时,Altair 是另一个很棒的库。您可以在 Anvil 上交互式运行此代码(需要帐户)或使用 此开源运行时在本地运行。

---

本文基于 Anvil 博客上的 P在 Altair 中绘图,并已获得许可重复使用。

接下来阅读什么
User profile image.
Shaun 通过在世界上最大的激光系统中模拟燃烧的聚变等离子体,认真地开始了编程。他爱上了 Python 作为数据分析工具,并且从未回头。现在他想把一切都变成 Python。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.