目录
1、下载Basemap
本人电脑win7,64位操作系统,使用Jupyter 和 Python3.6来完成。而Jupyter是安装在Anaconda上的。
当然也可以根据自己情况进行选择,不一定非要使用Jupyter。在Sublime3上也能实现。其它的没用过,所以不多说。
Basemap下载网址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
直接搜索Basemap,找到相关的下载链接。需要注意 Requires pyproj,也就是说我们需要先安装pyproj。
直接点击pyproj就可以直接跳到pyproj的下载位置
Pyproj根据自己系统选择下载版本:我的是Python36,电脑是64位操作系统
下载..............................................................................完成
2.安装Basemap
(1)如果使用Jupyter的话,请打开Anaconda Prompt
然后cd命令进入到存放刚才下载的两个whl文件的目录,直接使用pip install 文件名.whl进行安装,不过一定要先安装Pyproj文件,再安装Basemap文件。
(2)如果使用Sublime的话,请直接打开终端,然后cd命令进入到存放whl文件的文件夹,使用python -m pip install 文件名.whl安装。
安装顺序也是先安装Pyproj,然后安装Basemap。
按照上面的流程基本是没有什么问题的。至于其它安装方法就不复述了,坑很大,跳进去就没出来,最后灵光一闪想到了这个方法。
安装完成后记得要先在编辑器上from mpl_toolkits.basemap import Basemap,确定安装成功了,然后进行下一步。
或者直接复制下面的代码后运行:
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
plt.figure(figsize=(16,8))
chm = Basemap() # 绘制给出经纬度的底图,这里没给出经纬度,所以显示的是世界地图
chm.drawcoastlines() # 绘制海岸线
plt.show()
代码运行后会出现一副世界地图的线条图:
有问题解决问题,没问题继续往下看↓↓↓
3.参数说明
在下载地图包之前,先简单设置一下,让中国成为世界的中心,其实就是调整经纬度:
chm = Basemap(llcrnrlon=80, llcrnrlat=10, urcrnrlon=145, urcrnrlat=50, projection='lcc', lat_1=33, lat_2=45, lon_0=100)
参数解释:
llcrnrlon:longitude of lower left hand corner of the selected map domain.
地图上选中区域的左下角经度
llcrnrlat:latitude of lower left hand corner of the selected map domain.
地图上选中区域左下角的纬度
urcrnrlon:longitude of upper right hand corner of the selected map domain.
地图上选中区域右上角的经度
urcrnrlat:latitude of upper right hand corner of the selected map domain.
地图上选中区域右上角的纬度
这四个参数就是按照给出的经纬度坐标点来展示地图(其实就是利用左下角的坐标和右上角的坐标来确定一个矩形,经纬度的范围就是地图的大小)。
只给出上面四个参数,展示的效果是这样的
下面的参数和投影相关,投影内容及其丰富,所以仅供参考。
projection:这个参数就是选择的投影方式。lcc:Lambert Conformal 兰伯特正投影
正轴割圆锥等面积投影
投影参数:
起算纬度:0°或10°N
*经线:105°E 或110°E
标准纬线1:25°N
标准纬线2:45°N 或47°N
采用原因:
1、中国大部分地方属于中低纬度地区,故采用圆锥投影
2、中国疆域辽阔,纬度跨度很大(有50°的纬差),故必须用割投影(双标准纬线)来控制形变。
3、为强调各省区之间和中国与相邻国家之间的面积对比关系,采用等面积投影。
lat_0和lat_1必须给出两者中的一个,lat_2是可选的。
lon_0是必须给出的
下面是他们几个值的范围:
lat_0 = _validated_or_none(lat_0, 'lat_0', -90, 90)
lat_1 = _validated_or_none(lat_1, 'lat_1', -90, 90)
lat_2 = _validated_or_none(lat_2, 'lat_2', -90, 90)
lat_ts = _validated_or_none(lat_ts, 'lat_ts', -90, 90)
lon_0 = _validated_or_none(lon_0, 'lon_0', -360, 720)
lat_1和lat_2是和兰伯特正形圆锥投影相关的两个纬度 ,因为不懂这方面知识所以没办法解释。
还有lon_1和lon_2也不太明白
lat_0所需地图域的中心
lon_0所需地图域的中心(应该是指投影的角度)
调整后的数据
chm = Basemap(llcrnrlon=80, llcrnrlat=13, urcrnrlon=140, urcrnrlat=52, projection='lcc', lat_1=25, lat_2=45, lon_0=110)
然后再画上国境线
chm.drawcountries(linewidth=1.5)
4.地图包下载及导入
下面开始下载中国地图的数据包,https://gadm.org/download_country_v3.html
打开地址后国家选择China →ShapeFile文件。等待下载完成。
这里特意说明一下,下载的中国地图信息中是没有*省的,需要另行下载。同一个下载地址,同样的下载方法。
完成后读取相关信息
chm.readshapefile(r'C:\Users\Administrator\Desktop\ChinaMap\gadm36_CHN_1', 'states', drawbounds=True)
文件夹里有很多的gadm36_CHN文件,我只试了前三个,0是国家地图,1是省级地图,2是市级地图,应该是越往下划分的越细。剩下的自己试自己选择。
这是gadm36_CHN_1效果
这是gadm36_CHN_2文件效果
然后使用相同的方法添加*信息。
chm.readshapefile(r'C:\Users\Administrator\Desktop\*Map\gadm36_TWN_1', '*', drawbounds=True)
到这里中国地图就画完了。这是完整代码,其实还是很简单的(参数)。
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
plt.figure(figsize=(16, 8))
chm = Basemap(llcrnrlon=74, llcrnrlat=4, urcrnrlon=136, urcrnrlat=54, projection='lcc', lat_0=10, lon_0=100)
chm.drawcoastlines()
chm.drawcountries(linewidth=1.5)
chm.readshapefile(r'C:\Users\Administrator\Desktop\ChinaMap\gadm36_CHN_1', 'states', drawbounds=True)
chm.readshapefile(r'C:\Users\Administrator\Desktop\*Map\gadm36_TWN_1', '*', drawbounds=True)
plt.show()
下面就是按照各省份人口数量对地图进行颜色填充。
5.颜色填充
先简单来个颜色填充,大概了解一下流程:
from matplotlib.patches import Polygon
ax = plt.gca()
for nshape, seg in enumerate(m.states + m.*):
poly = Polygon(seg, facecolor='r')
ax.add_patch(poly)
大概就是这么个流程,如果想根据各省人口数量的多寡来进行颜色填充的话,我们还需要下载一个2010年全国人口普查的数据文件。http://www.stats.gov.cn/tjsj/pcsj/rkpc/6rp/indexce.htm
网址打开后左侧菜单栏【第一部分】【第一卷】【1-1 各地区户数、人口数和性别比】。下载的文件是excel格式。
下载完成后可以直接使用pandas的read_excel函数读取文件。为了后面操作方便事先手动将数据进行简单处理。
就是将上面红线框里的行删掉,只保留每列的标题就可以了。
import pandas as pd
pd.read_excel(r"C:\Users\Administrator\Desktop\A0101a.xls")
打印出来长这样:
下面开始颜色渲染:
(1)先创建一个空列表和一个空字典用来存放从地图信息上读取的省份名称和颜色。
statenames = []
colors = {}
(2)创建一个matplotlib.colors.LinearSegmentedColormap对象,将小数转为(red, green, blue, alpha)的元祖。后面会用到。
import matplotlib.cm as cm
cmap = cm.YlOrRd
也可以直接使用matplotlib.pyplot来导入
cmap = plt.YlOrRd # 因为上面已经导入了matplotlib.pyplot
然后创建两个极限值,用来最终生成颜色
vmax = 100000000
vmin = 2000000
(3)通过人数的极值生成颜色,然后渲染
for shapedict in m.states_info:
statename = shapedict['NL_NAME_1']
p = statename.split('|')
if len(p) > 1:
s = p[1]
else:
s = p[0]
s = s[:2]
if s == "黑龍":
s = "黑龙"
statenames.append(s)
pop = df["合计"][s]
colors[s] = cmap(np.sqrt((pop - vmin) / (vmax - vmin)))[:3]
ax = plt.gca()
for nshape, seg in enumerate(chm.states):
color = rgb2hex(colors[statenames[nshape]])
poly = Polygon(seg, facecolor=color, edgecolor=color)
ax.add_patch(poly)
plt.show()
因为没有*省的人口数据,所以这里没有进行渲染。
for shapedict in m.states_info:
statename = shapedict['NL_NAME_1']
statename["NL_NAME_1"]获取的是省名,类似于下面的格式:繁体名|简体名。
也有只是一个简体名的
还有一个特殊的就是黑龙江,它的简体是在前面的:
简繁体之间通过"|"符号分割,我们需要将简体名都取出来。
statenames.append(s)之前的代码就是在提取省名。都是Python的基础代码。就不多解释了。
pop = df["合计"][s]
上面的代码是借助DataFrame的行标签和列标签,取出各省的总人口
colors[s] = cmap(np.sqrt((pop - vmin) / (vmax - vmin)))[:3]
np.sqrt是numpy的基础函数,计算平方根
cmap将小数转换成rgba元祖。上面介绍了。至于怎么转换的,哈哈...
第四位是透明度,可要可不要。因为rgb2hex接收的参数是rgb或者rgba
color = rgb2hex(colors[statenames[nshape]]) 将rgb或rgba转换为十六进制的字符串
poly = Polygon(seg, facecolor=color, edgecolor=color)
ax.add_patch(poly)
文章参考:https://segmentfault.com/a/1190000010871928