欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

谈谈我常用的 6 种绘制地图的方法

最编程 2024-06-07 18:22:20
...

Boken


首先我们先介绍 Boken 绘制地图的方法

Bokeh 支持创建基本地图可视化和基于处理地理数据的地图可视化

画一张世界地图

from bokeh.plotting import figure, show
from bokeh.tile_providers import CARTODBPOSITRON, get_provider
from bokeh.io import output_notebook
output_notebook()
tile_provider = get_provider(CARTODBPOSITRON)
p = figure(x_range=(-2000000, 6000000), y_range=(-1000000, 7000000),
           x_axis_type="mercator", y_axis_type="mercator")
p.add_tile(tile_provider)
show(p)


微信图片_20220522155038.png


再画一张中国地图看看

from bokeh.plotting import curdoc, figure
from bokeh.models import GeoJSONDataSource
from bokeh.io import show
# 读入中国地图数据并传给GeoJSONDataSource
with open("china.json", encoding="utf8") as f:
    geo_source = GeoJSONDataSource(geojson=f.read())
# 设置一张画布
p = figure(width=500, height=500)
# 使用patches函数以及geo_source绘制地图
p.patches(xs='xs', ys='ys', source=geo_source)
show(p)


微信图片_20220522155042.png


我们通过 GEO 地理数据来绘制地图同样非常方便,但是地图看起来有一些单调,我们把不同的省份绘制成不同的颜色来看看

with open("china.json", encoding="utf8") as f:
    data = json.loads(f.read())
# 判断是不是  北京地区数据
def isBeijing(district):
    if 'beijing' in district['properties']['woe-name'].lower():
        return True
    return False
# data['features'] = list(filter(isInLondon, data['features']))
# 过滤数据
# 为每一个地区增加一个color属性
for i in range(len(data['features'])):
    data['features'][i]['properties']['color'] = ['red', 'blue', 'yellow', 'orange', 'gray', 'purple'][i % 6]
    data['features'][i]['properties']['number'] = random.randint(0, 20_000)
geo_source = GeoJSONDataSource(geojson=json.dumps(data))
p = figure(width=500, height=500, tooltips="@name, number: @number")
p.patches(xs='xs', ys='ys', fill_alpha=0.7,
        line_color='white',
        line_width=0.5,
        color="color",   # 增加颜色属性,这里的"color"对应每个地区的color属性
        source=geo_source)
p.axis.axis_label = None
p.axis.visible = False
p.grid.grid_line_color = None
show(p)


微信图片_20220522155045.png


可以看到已经有内味了,唯一美中不足的就是南海的十三段线没有展示出来


GeoPandas


GeoPandas 是基于 Pandas 的地图可视化工具,其数据结构完全继承自 Pandas,对于熟悉潘大师的同学来说还是非常友好的

还是先画一张世界地图

import pandas as pd
import geopandas
import matplotlib.pyplot as plt
%matplotlib inline
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
world.plot()
plt.show()


微信图片_20220522155140.png


这也是 geopandas 官网上的经典图片,可以看到非常简单,除去 import 代码,仅仅三行,就完成了地图的绘制

下面我们继续绘制中国地图,这次我们加上九段线信息

china_nine = geopandas.read_file(r"geojson/九段线GS(2019)1719号.geojson")
china = geopandas.read_file('china-new.json')
fig, ax = plt.subplots(figsize=(12, 8),dpi=80)
ax = china.plot(ax=ax, column='number')
ax = china_nine.plot(ax=ax)
plt.show()


微信图片_20220522155143.png


我们复用了前面处理的 china.json 数据,里面的 number 字段是随机生成的测试数据,效果与 Bokeh 不相上下


plotly


接下来我们介绍 plotly,这也是一个非常好用的 Python 可视化工具,如果要绘制地图信息,我们需要安装如下依赖

!pip install geopandas==0.3.0
!pip install pyshp==1.2.10
!pip install shapely==1.6.3

接下来我们先绘制一个世界地图

import plotly.graph_objects as go
fig = go.Figure(go.Scattermapbox(
    mode = "markers+lines",
    lon = [10, 20, 30],
    lat = [10, 20,30],
    marker = {'size': 10}))
fig.add_trace(go.Scattermapbox(
    mode = "markers+lines",
    lon = [-50, -60,40],
    lat = [30, 10, -20],
    marker = {'size': 10}))
fig.update_layout(
    margin ={'l':0,'t':0,'b':0,'r':0},
    mapbox = {
        'center': {'lon': 113.65000, 'lat': 34.76667},
        'style': "stamen-terrain",
        'center': {'lon': -20, 'lat': -20},
        'zoom': 1})
fig.show()

这里我们使用底层 API plotly.graph_objects.Choroplethmapbox 来绘制

微信图片_20220522155147.png


下面我们继续绘制中国地图,使用一个高级 API plotly.express.choropleth_mapbox

import pandas as pd
import plotly.express as px
import numpy as np
import json
with open(r"china_province.geojson", encoding='utf8') as f:
    provinces_map = json.load(f)
df = pd.read_csv(r'data.csv')
df.确诊 = df.确诊.map(np.log)
fig = px.choropleth_mapbox(
    df,
    geojson=provinces_map,
    color='确诊',
    locations="地区",
    featureidkey="properties.NL_NAME_1",
    mapbox_style="carto-darkmatter",
    color_continuous_scale='viridis',
    center={"lat": 37.110573, "lon": 106.493924},
    zoom=3,
)
fig.show()


微信图片_20220522155150.png


可以看出绘制出的交互式地图还是非常漂亮的,不过渲染速度有些感人,这个就看个人的需求了,如果你对渲染速度有要求,那么 Ployly 可能不是最好的选择~


Cartopy/Basemap


之所以把这两个库放到一起,是因为他们都是基于 Matplotlib 之上的,而随着 Python2 的不再维护,Basemap 也被 Matplotlib 放弃,Cartopy 随之转正,下面我们主要介绍 Cartopy 工具

Cartopy 利用了强大的 PROJ.4、NumPy 和 Shapely 库,并在 Matplotlib 之上构建了一个编程接口,用于创建发布高质量的地图

先来绘制一个世界地图

%matplotlib inline
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()
plt.show()


微信图片_20220522155339.png


这是一个 cartopy 绘制的非常经典且常见的世界地图,形式比较简单,下面我们增强该地图

import datetime
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.feature.nightshade import Nightshade
fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
date = datetime.datetime(2021, 12, 2, 21)
ax.set_title(f'Night time shading for {date}')
ax.stock_img()
ax.add_feature(Nightshade(date, alpha=0.2))
plt.show()


微信图片_20220522155343.png


我们通过上面的代码,绘制了当前时间世界昼夜图,还是很强的

下面我们继续绘制中国地图

上一篇: 深入探讨:不同领域的地图编辑器--从 D2D 地图编辑器到

下一篇: 如何做好基于地图的数据可视化?

推荐阅读