前情提要:不同的shp可能信息不一样可能出现用不了的情况,需要进行修改。关于修改部分会写在最后,如果对shp信息不太熟也可以先翻到最后看一下。
import cartopy.crs as ccrs
from cartopy.io.shapereader import Reader
import matplotlib.pyplot as plt
'''
loc为一个列表,储存了市的名称,例如loc=['北京','天津']
shp_records_generator是一个类名称为generator的数据,本例中储存了shp的信息,读取该数据的语句为shp_records_generator=Reader(市.shp).record()
该函数可以按loc中市的排列顺序返回loc中市在数据shp_records_generator中的索引。该索引从零开始。
'''
def location_index(shp_records_generator, loc):
n = 0 # n 代表地区的索引
loc_index = [] # 储存了目标地区的索引
for e in shp_records_generator: # 逐个循环shp中的信息
for f in loc: # 逐个循环需要绘制的区域
if f in e.attributes.get or f in e.attributes.get('省'): # shp中的数据看上去是以字典的形式存储的,比如 '市':'北京市'(该项需要读出自己的数据自行判断)
loc_index.append(n)
break
n = n + 1
return loc_index
shp_path = r"D:\BaiduNetdiskDownload\区划\市.shp"
shp_path1 = r"D:\BaiduNetdiskDownload\区划\省.shp"
proj = ccrs.Mercator() # 墨卡托投影
fig = plt.figure(figsize=(2, 2), dpi=300)
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
extent = [110, 115, 34, 41] # 显示图示经纬度范围
reader = Reader(shp_path)
readerProvince = Reader(shp_path1)
b = readerProvince.records()
a = reader.records() # print(list(a))可以查看具体的shp信息
city = ['太原', '阳泉', '长治', '晋城']
province = ['山西']
loc_Index = location_index(a, city)
loc_Index1 = location_index(b, province)
shp_list = list(reader.geometries())
shp_list1 = list(readerProvince.geometries())
for q in loc_Index1:
Shanxi = ax.add_geometries(shp_list1[q:q + 1], proj, edgecolor='k', facecolor='lightgrey', lw=0.4)
for m in loc_Index:
Shanxi = ax.add_geometries(shp_list[m:m+1], proj, edgecolor='k', facecolor='darkorange', lw=0.4)
ax.set_extent(extent, crs=proj)
ax.axis('off')
plt.savefig('shanxi_map1.png', dpi=fig.dpi, transparent=True) # 绘图背景为透明
plt.show()
最终的绘图结果为:
ps. 因为是要放入ppt里面的图片,所以没有显示经纬度,如果想要显示经纬度等信息的详细代码可以留言,后续可能会再写一篇。
针对本代码使用了print(list(a)[0:3])来查看shp的信息,如下:
[<Record: <shapely.geometry.polygon.Polygon object at 0x000001A30027BBE0>, {'省代码': 110000, '省': '北京市', '市代码': 110000, '市': '北京市', '类型': '直辖市'}, <fields>>, <Record: <shapely.geometry.polygon.Polygon object at 0x000001A3044E4AF0>, {'省代码': 120000, '省': '天津市', '市代码': 120000, '市': '天津市', '类型': '直辖市'}, <fields>>, <Record: <shapely.geometry.polygon.Polygon object at 0x000001A3044E4460>, {'省代码': 130000, '省': '河北省', '市代码': 130100, '市': '石家庄市', '类型': '地级市'}, <fields>>]
可以看到类似字典的显示,shp中一个索引对应的是一个市的全部信息,如:<Record: <shapely.geometry.polygon.Polygon object at 0x000001A30027BBE0>, {'省代码': 110000, '省': '北京市', '市代码': 110000, '市': '北京市', '类型': '直辖市'}, <fields>>
我写的函数location_index()就是通过提取shp里面的市的名称信息来,寻找目标市的索引,所以要按照自己显示出的shp信息规范来对函数进行修改。我需要看的信息就是 '市': '北京市',当我输入 '北京' 的时候它可以返回北京在shp信息的索引。修改函数中这一句即可
重新修改了这条语句if e.attributes.get('市') == f + '市' or e.attributes.get('省') == f + '省':
改为:if f in e.attributes.get or f in e.attributes.get('省'):
这样就能保证只要输入“山西”就能叠加山西省所有市的边界,或者输入“太原”或“太原市”都可以正确画出该市的边界