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

今天来讲一讲在日常工作生活中我常用的几种绘制地图的方法,下面我将介绍下面这些可视化库的地图绘制方法,当然绘制漂亮的可视化地图还有很多优秀的类库,没有办法一一列举

pyecharts、plotly、folium、bokeh、basemap、geopandas、cartopy

Boken

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

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

画一张世界地图

frombokeh.plottingimportfigure, show

frombokeh.tile_providersimportCARTODBPOSITRON, get_provider

frombokeh.ioimportoutput_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)

再画一张中国地图看看

frombokeh.plottingimportcurdoc, figure

frombokeh.modelsimportGeoJSONDataSource

frombokeh.ioimportshow

# 读入中国地图数据并传给GeoJSONDataSource

withopen("china.json", encoding="utf8")asf:

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)

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

withopen("china.json", encoding="utf8")asf:

data = json.loads(f.read())

# 判断是不是  北京地区数据

defisBeijing(district):

if'beijing'indistrict['properties']['woe-name'].lower():

returnTrue

returnFalse

# data['features'] = list(filter(isInLondon, data['features']))

# 过滤数据

# 为每一个地区增加一个color属性

foriinrange(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)

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

geopandas

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

还是先画一张世界地图

importpandasaspd

importgeopandas

importmatplotlib.pyplotasplt

%matplotlib inline

world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))

world.plot()

plt.show()

这也是 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()

我们复用了前面处理的 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

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

importplotly.graph_objectsasgo

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 来绘制

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

import pandas aspd

importplotly.expressaspx

importnumpyasnp

importjson

withopen(r"china_province.geojson", encoding='utf8')asf:

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()

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

Cartopy/Basemap

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

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

先来绘制一个世界地图

%matplotlib inline

importcartopy.crsasccrs

importmatplotlib.pyplotasplt

ax = plt.axes(projection=ccrs.PlateCarree())

ax.coastlines()

plt.show()

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

importdatetime

importmatplotlib.pyplotasplt

importcartopy.crsasccrs

fromcartopy.feature.nightshadeimportNightshade

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()

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

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

importcartopy.io.shapereaderasshpreader

importnumpyasnp

importmatplotlib.pyplotasplt

importcartopy.crsasccrs

importcartopy.featureascfeature

fromcartopy.mpl.gridlinerimportLONGITUDE_FORMATTER, LATITUDE_FORMATTER

fromcartopy.mpl.tickerimportLongitudeFormatter, LatitudeFormatter

importcartopy.io.shapereaderasshapereader

importmatplotlib.tickerasmticker

#从文件中加载中国区域shp

shpfile = shapereader.Reader(r'ne_10m_admin_0_countries_chn\ne_10m_admin_0_countries_chn.shp')

# 设置 figure 大小

fig = plt.figure(figsize=[8,5.5])

# 设置投影方式并绘制主图

ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))

ax.add_geometries(

shpfile.geometries(),

ccrs.PlateCarree())

ax.set_extent([70,140,0,55],crs=ccrs.PlateCarree())

plt.show()

使用 cartopy 绘制地图最大的特点就是灵活度高,那么相对应的代价就是编写代码也会更难一些,比如如果想要给不同省份填充不同颜色,我们需要编写的代码就有点多

importmatplotlib.patchesasmpatches

importmatplotlib.pyplotasplt

frommatplotlib.font_managerimportFontProperties

importshapely.geometryassgeom

importcartopy.crsasccrs

importcartopy.io.shapereaderasshpreader

font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)

defsample_data():

#    lons = [110, 115, 120, 122, 124 ]

lons = [124,122,120,115,110]

lats = [33,32,28,30,28]

returnlons, lats

#ax = plt.axes([0, 0, 1, 1], projection=ccrs.LambertConformal())

ax = plt.axes(projection=ccrs.PlateCarree())

ax.set_extent([70,140,0,55],crs=ccrs.Geodetic())

shapename ='admin_1_states_provinces'

states_shp = shpreader.natural_earth(resolution='10m', category='cultural', name=shapename)

lons, lats = sample_data()

# to get the effect of having just the states without a map "background"

# turn off the outline and background patches

ax.background_patch.set_visible(False)

ax.outline_patch.set_visible(False)

plt.title(u'China Province Level', fontproperties=font)

# turn the lons and lats into a shapely LineString

track = sgeom.LineString(zip(lons, lats))

track_buffer = track.buffer(1)

forstateinshpreader.Reader(states_shp).geometries():

# pick a default color for the land with a black outline,

# this will change if the storm intersects with our track

facecolor = [0.9375,0.9375,0.859375]

edgecolor ='black'

ifstate.intersects(track):

facecolor ='red'

elifstate.intersects(track_buffer):

facecolor ='#FF7E00'

ax.add_geometries([state], ccrs.PlateCarree(),

facecolor=facecolor, edgecolor=edgecolor)

# make two proxy artists to add to a legend

direct_hit = mpatches.Rectangle((0,0),1,1, facecolor="red")

within_2_deg = mpatches.Rectangle((0,0),1,1, facecolor="#FF7E00")

labels = [u'省份level1',

'省份level2']

plt.legend([direct_hit, within_2_deg], labels,

loc='lower left', bbox_to_anchor=(0.025,-0.1), fancybox=True, prop=font)

ax.figure.set_size_inches(14,9)

plt.show()

folium

folium 是建立在 Python 生态系统的数据应用能力和 Leaflet.js 库的映射能力之上的高级地图绘制工具,通过 Python 操作数据,然后在 Leaflet 地图中可视化,可以灵活的自定义绘制区域,并且展现形式更加多样化

首先是三行代码绘制世界地图

importfolium

# define the world map

world_map = folium.Map()

# display world map

world_map

接下来绘制中国地图

# 绘制边界

importjson

df = pd.read_csv(r'plotly-choropleth-mapbox-demo-master/data.csv')

# read china border 

withopen(r"plotly-choropleth-mapbox-demo-master/china_province.geojson", encoding='utf8')asf:

china = json.load(f)

chn_map = folium.Map(location=[40,100], zoom_start=4)

folium.Choropleth(

geo_data=china,

name="choropleth",

data=df,

columns=["地区","确诊"],

key_on="properties.NL_NAME_1",

fill_color="YlGn",

fill_opacity=0.7,

line_opacity=0.2,

legend_name="新冠确诊",

).add_to(chn_map)

folium.LayerControl().add_to(chn_map)

chn_map

作为专业地图工具,不仅渲染速度快,自定义程度也是非常高的,值得使用尝试

PyEcharts

最后我们介绍 PyEcharts,这款国产的精良可视化工具 

绘制世界地图

frompyechartsimportoptionsasopts

frompyecharts.chartsimportMap

frompyecharts.fakerimportFaker

c = (

Map()

.add("测试数据", [list(z)forzinzip(Faker.country, Faker.values())],"world")

.set_series_opts(label_opts=opts.LabelOpts(is_show=False))

.set_global_opts(

title_opts=opts.TitleOpts(title="Map-世界地图"),

visualmap_opts=opts.VisualMapOpts(max_=200),

)

)

c.render_notebook()

通过 Pyecharts 绘制地图的一个好处就是不需要处理 GEO 文件,我们直接出入国家名称,就可以自动匹配到地图上,非常方便

再绘制中国地图

c = (

Map()

.add("测试数据", [list(z)forzinzip(Faker.provinces, Faker.values())],"china")

.set_global_opts(

title_opts=opts.TitleOpts(title="Map-VisualMap(中国)"),

visualmap_opts=opts.VisualMapOpts(max_=200, is_piecewise=True),

)

)

c.render_notebook()

我们只需要把参数替换成 ”china“ 就可方便的绘制中国地图,真的很给力,当然对于 Pyecharts 还有很多种玩法,就不一一介绍了

综合上面的示例,我们可以看出, Pyecharts 绘制地图最为简单,非常适合新手学习使用;而 folium 和cartopy 则胜在自由度上,它们作为专业的地图工具,留给了使用者无限可能;至于 Plotly 和 Bokeh 则属于更高级的可视化工具,它们胜在画质更加优美,API 调用也更加完善

今天我们介绍了几种比较常用的绘制地图的类库,每一个工具都有其优缺点,我们只需要在选择的时候,明确目标,用心探索就好

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容