[Python/可视化/地图] 基于Python绘制地图
0 概述:基于Python绘制地图
1 基于 PyEcharts 绘制地图
PyEchart库
pyecharts
是一个基于 百度开源的Apache ECharts
的Python
数据可视化库。
ECharts
是一个使用JavaScript
实现的开源可视化库,而Pyecharts
则是 ECharts 的 Python 封装,使得在 Python 中使用 ECharts 变得更加方便。
CASE 绘制中国国的全国省级地图
- 安装依赖
pyecharts
# 需要注意,自从 v0.3.2 开始,为了缩减项目本身的体积以及维持 pyecharts 项目的轻量化运行,pyecharts 将不再自带地图 js 文件。为了绘制地图,还要单独安装对应的地图文件包:
echarts-china-provinces-pypkg
# 全球国家地图:世界地图和 213 个国家,包括中国地图 (可以根据自己的需求进行对应下载)
# echarts-countries-pypkg
# 中国省级地图
# echarts-china-provinces-pypkg
# 中国地级市地图
# echarts-china-cities-pypkg
# 中国县级地图
# echarts-china-counties-pypkg
# 中国区域地图
# echarts-china-misc-pypkg
查看版本安装情况
C:\Users\xxx> pip list | findstr "charts"
echarts-china-provinces-pypkg 0.0.3
pyecharts 2.0.8
pyecharts-jupyter-installer 0.0.3
-
准备数据
-
编写、运行 Python 脚本
from pyecharts.charts import Map
from pyecharts import options as opts
# @description CASE 绘制中国国的全国省级地图
# @updateTime 2025-10-08 15:11
# 准备数据
province_distribution = {
'河南省': 59.23, '北京市': 37.56, '河北省': 21, '辽宁省': 12, '江西省': 6,
'上海市': 20, '安徽省': 10, '江苏省': 16, '湖南省': 9, '浙江省': 13,
'海南省': 2, '广东省': 22, '湖北省': 8, '黑龙江省': 11, '澳门特别行政区': 1,
'陕西省': 11, '四川省': 7, '内蒙古自治区': 3, '重庆市': 3, '云南省': 6,
'贵州省': 2, '吉林省': 3, '山西省': 12, '山东省': 11, '福建省': 4,
'青海省': 1, '天津市': 1, '其他': 1
}
# 特别注意: 必须用 "省" 或 "市" 结尾,否则数据匹配不上 (例如: "xx省" ,"xx自治区" , "xx市", "xx特别行政区")
provinces = list(province_distribution.keys())
# provinces = ["北京", "上海", "广东", "江苏", "浙江", "四川", "湖北", "湖南", "河南", "山东"]
values = list(province_distribution.values())
# values = [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]
# 将数据转换为Pyecharts需要的格式
data = list(zip(provinces, values))
# 创建地图
map = Map(init_opts=opts.InitOpts(width="1000px", height="600px"))
map.add( # 添加1个图例
series_name="series_001" # 允许设置为空字符串(""),不显示图例
, data_pair=data # [list(z) for z in data]
, maptype="china" # 指定绘制地图区域
, is_map_symbol_show=False # 显示省份标签
# , is_selected=False # 是否默认选中 (此属性,已不再被支持)
)
map.set_global_opts(
title_opts=opts.TitleOpts(
title="中国地图",
pos_left="center", # 标题居中
pos_top="20px" # 标题位置
)
, legend_opts=opts.LegendOpts(is_show=True) # 显示图例
, visualmap_opts=opts.VisualMapOpts(max_=50)
)
map.render("china_map.html") # 渲染地图(生成HTML文件)
运行成功后,将输出1个html文件:
china_map.html
浏览器打开:
CASE 绘制指定省份的地级市数据,且替换掉默认的行政区划中文名称为自定义的英文名称
- 安装依赖
- 准备数据集
hubei.csv
Province | Province-Chinese | Number |
---|---|---|
Wuhan | 武汉市 | 10 |
Huang-gang | 黄冈市 | 9 |
Xiao-gan | 孝感市 | 8 |
Huang-shi | 黄石市 | 5 |
Shi-yan | 十堰市 | 5 |
Xian-ning | 咸宁市 | 2 |
Xiang-yang | 襄阳市 | |
Shen-nong-jia | 神农架林区 | 2 |
Shi-En | 恩施土家族苗族自治州 | |
Yi-Chang | 宜昌市 | |
Jing-zhou | 荆州市 | 2 |
Qian-jiang | 潜江市 | |
Jing-men | 荆门市 | 7 |
Tian-men | 天门市 | |
Xian-tao | 仙桃市 | 2 |
E-zhou | 鄂州市 | 2 |
Sui-zhou | 随州市 |
- 运行python脚本
from pyecharts.charts import Map
from pyecharts import options as opts
import pandas as pd
import os,sys
# @description CASE 绘制指定省份的地级市数据,且替换掉默认的行政区划中文名称为自定义的英文名称
# @updateTime 2025-10-08 16:07
# step1 准备数据
city = 'hubei' # 地级市名称(英文)
city_chinese = '湖北' # 地级市名称(中文)
#file = r'C:\Users\EDY\Desktop\map\{0}{1}'.format(city,'.csv') # 'C:\Users\EDY\Desktop\map\\hubei.csv'
#os.chdir("../dataset/");path=os.getcwd() + os.sep;file = path + r'{0}{1}'.format(city,'.csv')
file = os.path.abspath( os.path.join('..', 'dataset', city + '.csv') )
print(f"file:{file}");
data = pd.read_csv(file, encoding='gbk')
list = [list(z) for z in zip(data['Province'],data['Number'])]
areaNameMap = dict(zip(data['Province-Chinese'],data['Province'])) # 行政区划中文与英文映射关系
print(f"areaNameMap:{areaNameMap}") # {'武汉市': 'Wuhan', '黄冈市': 'Huang-gang', '孝感市': 'Xiao-gan', '黄石市': 'Huang-shi', '十堰市': 'Shi-yan', '咸宁市': 'Xian-ning', '襄阳市': 'Xiang-yang', '神农架林区': 'Shen-nong-jia', '恩施土家族苗族自治州': 'Shi-En', '宜昌市': 'Yi-Chang', '荆州市': 'Jing-zhou', '潜江市': 'Qian-jiang', '荆门市': 'Jing-men', '天门市': 'Tian-men', '仙桃市': 'Xian-tao', '鄂州市': 'E-zhou', '随州市': 'Sui-zhou'}
# step2 地图的初始化与参数配置
map = Map(opts.InitOpts(width='1200px',height='1200px'))
map.add( # 添加1个图例
series_name='province'
, data_pair=list
, maptype=city_chinese
, is_map_symbol_show = True
, name_map=areaNameMap
)
map.set_global_opts(
title_opts=opts.TitleOpts(title=city)
,visualmap_opts = opts.VisualMapOpts(
max_=2
, is_piecewise=False
, range_color=['#8EC0E4','#67D5B5']
)
)
map.set_series_opts(
label_opts=opts.LabelOpts(
font_size = 22 # font_size 调整字体大小
,font_family="Times New Roman" # 字体
,is_show=True
, color="blue" # 颜色
)
)
# step3 渲染(输出 html 文件)
map.render(city + '.html')
浏览器打开:
hubei.html
推荐文献
- Echarts
参考文献
"把北京改为北京市,如果有自治区,就写,比如内蒙古自治区,湖南省"
"为啥是要用拼音呢?因为项目中所画的图是要投国外期刊,需要转换成英文,那这样的话,需要有一个中英文转换,也就是代码中namemap的作用"
2 基于 Geopandas + geopandas 库绘制地图
Geopandas 与 geopandas 库的介绍
- GeoPandas 库
一个开源的、用于处理地理数据的Python库,它基于Pandas和Shapely,提供了方便的地理数据操作和可视化功能。
它扩展了Pandas库的功能,使得在Python中可以方便地处理地理空间数据。
GeoDataFrame
是GeoPandas
中的一个核心数据结构,它继承自Pandas
的DataFrame
,但增加了对地理空间数据的支持。
- Geopandas.GeoDataFrame 组件
GeoDataFrame
是一个表格型的数据结构,它不仅包含了数据的属性信息,还包含了地理信息,即几何对象。
这些几何对象可以是点(Point),线(LineString),或者多边形(Polygon)等。
每个GeoDataFrame
都有一个名为"geometry
"(几何学)的列,用来存储几何对象,这使得GeoDataFrame
能够与GIS
软件中的矢量数据进行交互。
- geodatasets 库
一个用于获取和缓存空间数据示例文件的 Python 包。
它提供了一个 API,可以从包含地理空间信息的外部托管数据集中提取链接或下载数据,这些数据集对于说明性和教育目的非常有用。
- 安装
pip install geodatasets
CASE 基于经纬度数据集,绘制中国地图 by geopandas + matplotlib 【TODO】
import geopandas as gpd
import matplotlib.pyplot as plt
import pandas as pd
import os
# @description 基于经纬度数据集,绘制中国地图 by geopandas + matplotlib
# @note 此脚本尚无法直接运行
# @reference-doc
# [1] R-ggplot2 标准中国地图制作 【推荐】 - Weixin/DataCharm - https://mp.weixin.qq.com/s?__biz=Mzg3MDY4ODI3MQ==&mid=2247497916&idx=1&sn=7d41c62dce027ef16e71c137898f4819&source=41&poc_token=HNIl5mijRifNCiMyGRCsMnIWbie0xhO1sSFFfMKC
# [2] Python-geopandas 中国地图绘制 【推荐】 - 腾讯云/DataCharm - https://cloud.tencent.com/developer/article/1790603
# @updateTime 2025-10-08 16:07
file = os.path.abspath( os.path.join('..', 'dataset', '中国省级地图GS(2019)1719号.geojson') ) # https://github.com/dlming123/China-map-information/blob/main/%E4%B8%AD%E5%9B%BD%E7%9C%81%E7%BA%A7%E5%9C%B0%E5%9B%BEGS%EF%BC%882019%EF%BC%891719%E5%8F%B7.geojson
nine = os.path.abspath( os.path.join('..', 'dataset', '九段线GS(2019)1719号.geojson') ) # https://github.com/dlming123/China-map-information/blob/main/%E4%B9%9D%E6%AE%B5%E7%BA%BFGS%EF%BC%882019%EF%BC%891719%E5%8F%B7.geojson
china_main = gpd.read_file(file)
china_nine = gpd.read_file(nine)
fig, ax = plt.subplots(figsize=(8,5),dpi=200,)
plt.rcParams['font.family'] = ['Times New Roman']
ax = china_main.geometry.to_crs(epsg=2343).plot(fc="white",ec="black",linewidth=.8,ax=ax)
ax = china_nine.geometry.to_crs(epsg=2343).plot(color="gray",linewidth=.9,ax=ax)
# 创建散点数据集 scatter
scatter_data = [
[29.580000, 106.550000, 'cluster1', 1],
[40.705295, 114.931254, 'cluster1', 3],
[31.366458, 118.381979, 'cluster1', 2],
[32.935000, 117.365000, 'cluster1', 2],
[32.630000, 116.970000, 'cluster1', 4]
## ... more data
]
# 指定列名
scatter_columns = ['lat', 'lon', 'class', 'data']
# 创建 DataFrame
scatter = pd.DataFrame(scatter_data, columns=scatter_columns)
scattergdf = gpd.GeoDataFrame(
scatter, geometry=gpd.points_from_xy(scatter.lon, scatter.lat),
crs="EPSG:4326"
)
scattergdf.head();
scattergdf_2343 = scattergdf.to_crs(epsg=2343, inplace=True)
# china_nine_2343 = //todo
for loc, size,class_name in zip(scattergdf_2343.geometry.representative_point(),\
scattergdf_2343["data"],scattergdf_2343["class"]):
ax.scatter(loc.x,loc.y,s=10*size,fc=class_color[class_name],ec="black",lw=.5,zorder=2)
#添加刻度线
for spine in ['top','left',"bottom","right"]:
ax.spines[spine].set_color("none")
#ax.set_xlim(china_nine_2343.geometry[0].x-500000, china_nine_2343.geometry[1].x)
#ax.set_ylim(china_nine_2343.geometry[0].y, china_nine_2343.geometry[1].y)
ax.set_xticks([])
ax.set_yticks([])
#单独绘制图例散点
ax.scatter([], [], c='#E21C21', s=30, label='cluster1',ec="black",lw=.5)
ax.scatter([], [], c='#3A7CB5', s=30, label='cluster2',ec="black",lw=.5)
ax.scatter([], [], c='#51AE4F', s=30, label='cluster3',ec="black",lw=.5)
ax.scatter([], [], c='white', s=1*10,label='1', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=2*10,label='2', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=3*10,label='3', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=4*10,label='4', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=5*10,label='5', edgecolor='black',lw=.5)
ax.legend(frameon=False,ncol=8,loc="upper center",
fontsize=9,columnspacing=.2)
ax.text(.91,-0.02,'\nVisualization by DataCharm',transform = ax.transAxes,
ha='center', va='center',fontsize = 6,color='black')
#添加南海小地图
ax_child = fig.add_axes([0.688, 0.125, 0.2, 0.2])
ax_child = china_main.geometry.to_crs(epsg=2343).plot(ax=ax_child,
fc="white",
ec="black",)
ax_child = china_nine.geometry.to_crs(epsg=2343).plot(ax=ax_child,
color="gray",
linewidth=.9,
)
for loc, size,class_name in zip(scattergdf_2343.geometry.representative_point(),\
scattergdf_2343["data"],scattergdf_2343["class"]):
ax_child.scatter(loc.x,loc.y,s=10*size,fc=class_color[class_name],ec="black",lw=.5,zorder=2)
#ax_child.set_xlim(china_nine_2343.geometry[2].x, china_nine_2343.geometry[3].x)
#ax_child.set_ylim(china_nine_2343.geometry[2].y, china_nine_2343.geometry[3].y)
# 移除子图坐标轴刻度,
ax_child.set_xticks([])
ax_child.set_yticks([])
# 添加南海小地图
ax_child = fig.add_axes([0.688, 0.125, 0.2, 0.2])
ax_child = (
china_main
.geometry
.to_crs(epsg=2343)
.plot(ax=ax_child,
fc="white",
ec="black",)
);
ax_child = china_nine.geometry.to_crs(epsg=2343).plot(ax=ax_child,
color="gray",
linewidth=.9,
)
for loc, size,class_name in zip(scattergdf_2343.geometry.representative_point(),\
scattergdf_2343["data"],scattergdf_2343["class"]):
ax_child.scatter(loc.x,loc.y,s=10*size,fc=class_color[class_name],ec="black",lw=.5,zorder=2)
#ax_child.set_xlim(china_nine_2343.geometry[2].x, china_nine_2343.geometry[3].x)
#ax_child.set_ylim(china_nine_2343.geometry[2].y, china_nine_2343.geometry[3].y)
# 移除子图坐标轴刻度,
ax_child.set_xticks([])
ax_child.set_yticks([])
#单独绘制图例散点
ax.scatter([], [], c='#E21C21', s=30, label='cluster1',ec="black",lw=.5)
ax.scatter([], [], c='#3A7CB5', s=30, label='cluster2',ec="black",lw=.5)
ax.scatter([], [], c='#51AE4F', s=30, label='cluster3',ec="black",lw=.5)
ax.scatter([], [], c='white', s=1*10,label='1', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=2*10,label='2', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=3*10,label='3', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=4*10,label='4', edgecolor='black',lw=.5)
ax.scatter([], [], c='white', s=5*10,label='5', edgecolor='black',lw=.5)
ax.legend(frameon=False,ncol=8,loc="upper center",
fontsize=9,columnspacing=.2)
CASE 使用geopandas提取地理信息数据,并绘制地图
- 推荐文献
中国科学院大学 环境科学博士
http://datav.aliyun.com/portal/school/atlas/area_selector
推荐文献
参考文献
https://github.com/mattijn/topojson/issues/224
https://github.com/geopandas/geopandas/issues/2751
https://stackoverflow.com/questions/76548222/how-to-get-maps-in-geopandas-after-datasets-are-removed
3 基于 folium 库绘制交互式地图
folium 库的介绍
- Folium 库
Folium是基于
Leaflet.js
的一个Python库,可以用于创建交互式地图
Python可以使用多种库和工具来创建地图应用。其中,最常用的是folium
库,它可以让你使用Python创建交互式地图。
你可以使用folium库加载地图数据、添加标记(folium.Marker
)和图层,以及添加交互功能(folium.Popup
:弹出窗口)。
- 安装
pip install folium
CASE 创建基本地图
import folium
# 创建基本地图
m = folium.Map(location=[45.5236, -122.6750], zoom_start=13)
# 保存地图为HTML文件
m.save('map.html')
CASE 添加标记和图层
# 添加标记和图层: 可以在地图上添加标记和图层,以增强地图的表现力
## 添加标记
folium.Marker([45.5236, -122.6750], popup='Portland').add_to(m)
## 添加多边形
folium.Polygon(locations=[[45.5236, -122.6750],
[45.5215, -122.6770],
[45.5245, -122.6790]],
color='blue', weight=2.5).add_to(m)
## 添加热力图
from folium.plugins import HeatMap
data = [[45.5236, -122.6750], [45.5215, -122.6770], [45.5245, -122.6790]]
HeatMap(data).add_to(m)
## 保存地图
m.save('map_with_layers.html')
4 基于 MATPLOTLIB + Basemap/Cartopy 库绘制静态地图
-
Matplotlib
是一个强大的数据可视化库,可以用于绘制静态地图。 -
要使用Matplotlib绘制地图,首先需要安装Matplotlib和Basemap
Basemap
即将消失,并在不久的将来被Cartopy
取代
pip install matplotlib basemap
CASE 绘制基本地图,并添加地理数据
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
# 创建地图对象
m = Basemap(projection='mill', llcrnrlat=-60, urcrnrlat=90, llcrnrlon=-180, urcrnrlon=180, resolution='c')
# 绘制海岸线和国家边界
m.drawcoastlines()
m.drawcountries()
# 显示地图
# plt.show()
# 添加地理数据: 可以将更多的地理数据添加到地图中,例如城市、河流等
## 绘制河流和城市
m.drawrivers(color='blue')
m.drawstates()
m.drawcounties()
## 添加城市标记
lat, lon = 40.7128, -74.0060 # 纽约市的经纬度
x, y = m(lon, lat)
m.plot(x, y, 'ro') # 红色圆点
plt.text(x, y, 'New York', fontsize=12)
# 显示地图
plt.show()
推荐文献
参考文献
Z 总结
Python可以使用多种地理信息的库和工具来创建地图应用。其中,最常用的是
folium
库,它可以让你使用Python创建交互式地图。
你可以使用folium库加载地图数据、添加标记和图层,以及添加交互功能。
另外,还有其他库如geopandas和plotly也可以用来创建地图应用。
Y 推荐文献
X 参考文献

本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!