如何在 Altair 中使用 GeoJSON 数据制作地图?
How can I make a map using GeoJSON data in Altair?
我对制图和 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 制作不列颠群岛的地图?
在此示例中,data.us_10m.url
是一个字符串变量,其中字符串指定 URL 到 geojson file 包含 state
特征中的美国州界。如果您想使用其他 geojson 文件,可以在该示例中替换它的 URL。
您提到的示例使用的是 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
解释 geojson
和 topojson
结构化 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])
通过漂亮地打印变量来检查创建的 GeoJSON var_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
)
内联 TopoJSON
TopoJSON 是 GeoJSON 的扩展,其中 features
的 geometry
是从名为 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
作为 GeometryCollection
.[=70 存储在键 data
中=]
注意:键名 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
还有一个 shorthand 可以从 topojson
文件中提取对象,如果这个文件可以被 URL 访问:
alt.topo_feature(url, feature)
Altair 示例,其中 topojson
文件由 URL
引用
# 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
文件没有这样的 shorthand 并且应该按如下方式链接:
alt.Data(url, format)
Altair 示例,其中 geojson
文件由 URL
引用
# 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/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 制作不列颠群岛的地图?
在此示例中,data.us_10m.url
是一个字符串变量,其中字符串指定 URL 到 geojson file 包含 state
特征中的美国州界。如果您想使用其他 geojson 文件,可以在该示例中替换它的 URL。
您提到的示例使用的是 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
解释 geojson
和 topojson
结构化 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])
通过漂亮地打印变量来检查创建的 GeoJSON var_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
)
内联 TopoJSON
TopoJSON 是 GeoJSON 的扩展,其中 features
的 geometry
是从名为 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
作为 GeometryCollection
.[=70 存储在键 data
中=]
注意:键名 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还有一个 shorthand 可以从 topojson
文件中提取对象,如果这个文件可以被 URL 访问:
alt.topo_feature(url, feature)
Altair 示例,其中 topojson
文件由 URL
# 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
文件没有这样的 shorthand 并且应该按如下方式链接:
alt.Data(url, format)
Altair 示例,其中 geojson
文件由 URL
# 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
)