地理信息分析常用的软件包括ArcGIS, GeoDa, Gephi等。但是python的geopandas库同样也能够做到。
LEO在最近的项目中遇到一个小case。数据结构非常简单,变量分别为省份、A、B。省份不用多说,A和B都为连续型变量,A的取值范围在[0,40],B的取值在[0,2000],hist当然可以分别完成变量A和B层次上各省份的排序,但同时也很好奇基于同一省份,A和B的变动是不是一致的(即是不是A比较多的省份,B也比较多呢)
如果能直接展示在地图上,可不是直接多了嘛。
一、找到地理数据
首先,需要把原数据里作为名义变量的“省份”匹配上地理信息,简单来说,需要先去找.shp后缀的中国省份边界数据。
中科院资源环境科学与数据中心,其他地理数据整理平台,以及Github上都有相应的资源。我选择下载了中科院资源环境科学与数据中心的省份数据。注,中科院需要提前拿邮箱注册登陆才可以下载。
二、匹配原始数据中的“省份”
将原数据和.shp数据按照省份匹配起来,这里需要注意的是原数据里的省份写法必须和.shp中的一致,比如.shp中写的是“北京市”,那么原数据里的省份就不能够出现“北京”,必须也加上“市”字。
Geopandas就在此时登场了。
当然,如果没有这个库的话,需要先在terminal或者猪皮特里pip install geopandas
将geopandas和pandas挨个引用,读入省份边界数据和原始数据。省份边界数据用的是gpd.read_file。
import geopandas as gpd
import pandas as pd
china_provinces = gpd.read_file('省份边界数据.shp')
df=pd.read_excel('原始数据.xlsx', header=0)
先进行一下汇总(groupby),因为这里原数据是从市级层面匹配到省级层面,原市级层面的两变量水平没有汇总
summed_data=df.groupby('省份').agg({'变量A':'sum','变量B':'sum'}).reset_index()
现在得到的summed_data才是接下来真正需要的原数据
开始匹配,使用merge函数
merged_data=china_provinces.merge(summed_data, left_on='省', right_on='省份')
这里left_on写的是省份边界数据中表示省份的列名,right_on是自己原数据中表示省份的列名
三、matplotlib开始画图
先绘制省份边界,再绘制表格数据
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, figsize=(10, 10))
# 绘制省份边界
china_provinces.plot(ax=ax, color='lightgrey')
# 绘制表格数据
merged_data.plot(ax=ax,column='变量A',legend=True,cmap='OrRd',legend_kwds={'label':"numbers"})
plt.show()
这里有几处可以自行调整,除了画面大小相关的参数外,省份边界中的color以及绘制表格数据下的cmap都能改变颜色,如果某一省份的变量A水平缺失,在地图上该省份会呈现出lightgrey这一颜色。OrRd指的是这张地图使用了从橘到红的映射,也可以换成其他颜色。
label对应的numbers可以替换为其他标签,但是目前中文标签还不太好显示。
画出来的图,长下面这个样子。也可以去掉坐标和方框。
# 去掉坐标和方框
ax.set_axis_off()
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['right'].set_color('none')
这么一来,依据省份颜色的深浅,能够比较明显看出来变量A水平在前的省份是哪些。
变量B的图同样也可以按照上面的代码画下来。
保存图片,就可以拿来用啦。
plt.savefig('图.png')
反思
如果要反映出A和B上的变动是否一致,除了分别画两张图,还有一种可行的方式是分别构造各省在变量A和B上的排名。但缺点也是显而易见的,省份间在两变量上的水平难以比较。
,