Python 数据可视化:Altair 使用全解析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 数据可视化:Altair 使用全解析相关的知识,希望对你有一定的参考价值。

参考技术A

ggplot2 是 R 的作图工具包,可以使用非常简单的语句实现非常复杂漂亮的效果。然而不幸的是,ggplot2 并不支持 Python。

在 Python 中,我们常使用 matplotlib 用于可视化图形,matplotlib是一个很强大的可视化库,但是它有着很严重的局限性。matplotlib 的使用非常灵活,这可以说的上是它的一个优点,但是当我们想为图形加一个小小的功能的时候,它的繁琐操作会让我们举步维艰。除此之外,matplotlib 的两种界面(面向对象界面、基于状态的界面)令人相当困惑,对于新手很不友好。即使对于多年使用 matplotlib 的人而言,他们也无法完全掌握这些操作。最后不得不说的是,用 matplotlib 制作交互式图表是一件相当困难的事情。

Altair 是 Vega-Lite 的包装器。Vega-Lite 是 javascript 的高级可视化库,它最最重要的特点是,它的API是基于图形语法的。

https://github.com/altair-viz/altair

什么是图形语法呢? 图形语法听起来有点像一个抽象的功能,值得注意的是,它是 Altair 和其他 Python 可视化库之间最主要的区别。Altair 符合我们人类可视化数据的方式和习惯,Altair 只需要三个主要的参数:

基于以上三个参数,Altair 将会选择合理的默认值来显示我们的数据。

Altair 最让人着迷的地方是,它能够合理的选择颜色。如果我们在 Encoding 中指定 变量类型为量化变量 ,那么 Altair 将会使用连续的色标来着色(默认为 浅蓝色-蓝色-深蓝色)。如果 变量类型指定为类别变量 ,那么 Altair 会为每个类别赋予不同的颜色。(例如 红色,黄色,蓝色)

让我们来看一个具体的例子,如下所示,我们组织了6个国家和它们所对应的人口数据,除此之外,还有相应的收入数据:

首先我们绘制每个国家的人口数据:

如何在 Altair 中使用 GeoJSON 数据制作地图?

【中文标题】如何在 Altair 中使用 GeoJSON 数据制作地图?【英文标题】:How can I make a map using GeoJSON data in Altair? 【发布时间】:2019-09-19 06:07:18 【问题描述】:

我对地图和 Altair/Vega 非常陌生。有an example in the Altair documentation for how to make a map starting with an outline of US states,基本上是用:

states = alt.topo_feature(data.us_10m.url, feature='states')

# US states background
background = alt.Chart(states).mark_geoshape(
    fill='lightgray',
    stroke='white'
)

但我想在不列颠群岛绘制点,而不是。由于 vega 数据集中只有美国和世界地图,我必须创建自己的 GeoJSON,不是吗?

所以我尝试通过运行一些命令行命令from this blog post,从世界地图获取不列颠群岛的 GeoJSON,即,

ogr2ogr -f GeoJSON -where "adm0_a3 IN ('GBR','IRL','IMN','GGY','JEY','GBA')" subunits.json ne_10m_admin_0_map_subunits/ne_10m_admin_0_map_subunits.shp

这似乎创建了一个 GeoJSON 文件 subunits.json,它可能代表不列颠群岛。但是我怎样才能把它带入 Altair 呢?或者还有其他方法可以使用 Altair 制作不列颠群岛的地图吗?

【问题讨论】:

【参考方案1】:

在此示例中,data.us_10m.url 是一个字符串变量,其中该字符串指定指向 geojson file 的 URL,该 URL 包含 state 功能中的美国州界。如果您想使用其他 geojson 文件,可以在该示例中替换其 URL。

【讨论】:

当我将 URL 提供给我的文件时,我总是得到一张空白地图。也许我拥有的文件不是geojson文件?或者也许我没有选择正确的功能(不确定那是什么)?我在这里完全不知所措。 功能名称应该是 JSON 文件顶层“对象”映射中的键之一。 嗯,我好像没有。也许它不是geojson文件?它开始于 "type": "FeatureCollection", "name": "ne_10m_admin_0_map_subunits", "crs": "type": "name", "properties": "name": "urn:ogc:def:crs:OGC:1.3:CRS84" , 啊,是的,我认为对于 geoshapes 你需要"type":"Topology" 您的文件是geojson 文件,但 Altair 中的示例使用的是topojson【参考方案2】:

您引用的示例是使用topojson 结构化数据,而您有geojson 结构化数据。所以你可能需要:

# remote geojson data object
url_geojson = 'https://raw.githubusercontent.com/mattijn/datasets/master/two_polygons.geo.json'
data_geojson_remote = alt.Data(url=url_geojson, format=alt.DataFormat(property='features',type='json'))

# chart object
alt.Chart(data_geojson_remote).mark_geoshape(
).encode(
    color="properties.name:N"
).project(
    type='identity', reflectY=True
)

更新:从 Altair 3.3.0 版开始,GeoDataFrames (geopandas) 直接为 supported。任何支持__geo_interface__ 的对象也是如此。


如需更多见解,请继续阅读!

这里下面讨论变体:

    内嵌 GeoJSON 内联 TopoJSON 来自 URL 的 TopoJSON 来自 URL 的 GeoJSON

解释geojsontopojson 结构化json 文件之间的区别以及它们在Altair 中的用法

import geojson
import topojson
import pprint
import altair as alt

内嵌 GeoJSON

我们首先创建一个包含两个特征的集合,即两个相邻的多边形。

我们将以 GeoJSON 数据格式创建的两个多边形的示例。:

feature_1 = geojson.Feature(
    geometry=geojson.Polygon([[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]]),
    properties="name":"abc"
)
feature_2 = geojson.Feature(
    geometry=geojson.Polygon([[[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]]),
    properties="name":"def"
)
var_geojson = geojson.FeatureCollection([feature_1, feature_2])

通过漂亮地打印变量var_geojson来检查创建的GeoJSON

pprint.pprint(var_geojson)
'features': ['geometry': 'coordinates': [[[0, 0],
                                             [1, 0],
                                             [1, 1],
                                             [0, 1],
                                             [0, 0]]],
                            'type': 'Polygon',
               'properties': 'name': 'abc',
               'type': 'Feature',
              'geometry': 'coordinates': [[[1, 0],
                                             [2, 0],
                                             [2, 1],
                                             [1, 1],
                                             [1, 0]]],
                            'type': 'Polygon',
               'properties': 'name': 'def',
               'type': 'Feature'],
 'type': 'FeatureCollection'

可以看出,两个Polygon Features 嵌套在features 对象中,geometry 是每个feature 的一部分。

Altair 能够使用 format 中的 property 键解析嵌套的 json 对象。下面是一个例子:

# inline geojson data object
data_geojson = alt.InlineData(values=var_geojson, format=alt.DataFormat(property='features',type='json')) 

# chart object
alt.Chart(data_geojson).mark_geoshape(
).encode(
    color="properties.name:N"
).project(
    type='identity', reflectY=True
)

内联拓扑JSON

TopoJSON 是 GeoJSON 的扩展,其中 featuresgeometry 来自名为 arcs 的***对象。这使得在几何上应用哈希函数成为可能,因此每个共享的arc 应该只存储一次。

我们可以将var_geojson变量转换成topojson文件格式结构:

var_topojson = topojson.Topology(var_geojson, prequantize=False).to_json()
var_topojson
'arcs': [[[1.0, 1.0], [0.0, 1.0], [0.0, 0.0], [1.0, 0.0]],
          [[1.0, 0.0], [2.0, 0.0], [2.0, 1.0], [1.0, 1.0]],
          [[1.0, 1.0], [1.0, 0.0]]],
 'objects': 'data': 'geometries': ['arcs': [[-3, 0]],
                                      'properties': 'name': 'abc',
                                      'type': 'Polygon',
                                     'arcs': [[1, 2]],
                                      'properties': 'name': 'def',
                                      'type': 'Polygon'],
                      'type': 'GeometryCollection',
 'type': 'Topology'

现在嵌套的geometry 对象被arcs 替换,并通过索引引用***arcs 对象。我们现在可以拥有多个objects,而不是单个FeatureCollection,其中我们转换的FeatureCollection 存储在密钥data 中作为GeometryCollection

注意:键名 data 是任意的,并且在每个数据集中都不同。

Altair 能够使用format 中的feature 键解析topojson 格式结构中的嵌套data 对象,同时声明它是topojson type。下面是一个例子:

# inline topojson data object
data_topojson = alt.InlineData(values=var_topojson, format=alt.DataFormat(feature='data',type='topojson')) 

# chart object
alt.Chart(data_topojson).mark_geoshape(
).encode(
    color="properties.name:N"
).project(
    type='identity', reflectY=True
)

来自 URL 的 TopoJSON

如果该文件可通过 URL 访问,则还存在从 topojson 文件中提取对象的简写:

alt.topo_feature(url, feature)

topojson 文件由 URL 引用的 Altair 示例

# remote topojson data object
url_topojson = 'https://raw.githubusercontent.com/mattijn/datasets/master/two_polygons.topo.json'
data_topojson_remote = alt.topo_feature(url=url_topojson, feature='data')

# chart object
alt.Chart(data_topojson_remote).mark_geoshape(
).encode(
    color="properties.name:N"
).project(
    type='identity', reflectY=True
)

来自 URL 的 GeoJSON

但对于可通过 URL 访问的 geojson 文件,则没有这样的简写,应按如下方式链接:

alt.Data(url, format)

geojson 文件由 URL 引用的 Altair 示例

# remote geojson data object
url_geojson = 'https://raw.githubusercontent.com/mattijn/datasets/master/two_polygons.geo.json'
data_geojson_remote = alt.Data(url=url_geojson, format=alt.DataFormat(property='features',type='json'))

# chart object
alt.Chart(data_geojson_remote).mark_geoshape(
).encode(
    color="properties.name:N"
).project(
    type='identity', reflectY=True
)

【讨论】:

以上是关于Python 数据可视化:Altair 使用全解析的主要内容,如果未能解决你的问题,请参考以下文章

无法将 altair 可视化作为弹出窗口插入到叶地图中

22个 Python 绘图包,囊括几乎所有的可视化需求

Tableau可视化分析实战系列Tableau基础概念全解析 -数据结构及字段

22个Python绘图包汇总,超实用的那种

面向小白的最全 Python 可视化教程,超全的!

如何更改 altair 中 geo_shape 的限制(python vega-lite)