geopandas学习(六) geoplot
文章参考:参考
在前面的基于geopandas的空间数据分析系列文章中,我们已经对geopandas的基础知识、基础可视化,以及如何科学绘制分层设色地图展开了深入的学习,而利用geopandas+matplotlib进行地理可视化固然能实现常见的地图可视化,且提供了操纵图像的极高自由度,但对使用者matplotlib的熟悉程度要求较高,制作一幅地图可视化作品往往需要编写较多的代码。
而geoplot基于geopandas,提供了众多高度封装的绘图API,很大程度上简化了绘图难度,就像seaborn之于matplotlib。
1.geoplot基础
1.1 从一个简单的例子出发
我们下面所使用到的数据:nyc-boroughs.geojson,记录了纽约的行政区域面文件:
import geopandas as gpd
%matplotlib inline
# 读入纽约行政区域面文件
nyc_boroughs = gpd.read_file('geometry/nyc-boroughs.geojson')
nyc_boroughs.head()
# 读入纽约车祸记录点文件
nyc_collision_factors = gpd.read_file('geometry/nyc-collision-factors.geojson')
nyc_collision_factors.head()
首先我们使用geoplot中的polyplot来绘制纽约行政区划,这里使用geoplot自带的Albers等面积投影作为投影:
import geoplot as gplt
import geoplot.crs as gcrs
import matplotlib.pyplot as plt
ax = gplt.polyplot(df=nyc_boroughs,
projection=gcrs.AlbersEqualArea())
plt.savefig("图4.png", bbox_inches='tight', pad_inches=0, dpi=300)
接着我们使用geoplot中的pointplot将点叠加到图4上:
ax = gplt.polyplot(df=nyc_boroughs,
projection=gcrs.AlbersEqualArea())
ax = gplt.pointplot(df=nyc_collision_factors,
s=2,
color='grey',
alpha=0.2,
linewidth=0, # 设置轮廓粗细为0
ax=ax)
plt.savefig("图5.png", bbox_inches='tight', pad_inches=0, dpi=300)
为了让车祸密集的区域更突出,我们将点图层换成核密度图层:
ax = gplt.polyplot(df=nyc_boroughs,
projection=gcrs.AlbersEqualArea())
# 叠加核密度图层
ax = gplt.kdeplot(df=nyc_collision_factors,
cmap='Reds',
shade=True,
shade_lowest=True,
clip=nyc_boroughs,
ax=ax)
plt.savefig("图6.png", bbox_inches='tight', pad_inches=0, dpi=300)
从这个简单的例子中我们可以大致了解到,geoplot在geopandas处理好的数据基础上,针对不同类型图层封装了各自不同的API,由用户自主传入对应类型的矢量数据进行图层叠加,以得到最终结果,且可以兼容matplotlib。
譬如上面我们最终使用plt.savaefig()对图片进行保存,下面我们就来详细学习geoplot的基础知识。
1.2 geoplot绘图API
在geoplot中内置了功能丰富的绘图API,只需要传入GeoDataFrame格式的矢量数据即可进行绘图(但切记geoplot中传入的数据必须为WGS84地理坐标系,所有的投影转换在geoplot各绘图函数内部传参实现即可!)
1.2.1 Pointplot
geoplot中的pointplot即为散点图,其针对点数据进行可视化,其主要参数如下:
- df:传入对应的GeoDataFrame对象
- projection:用于指定投影坐标系,传入geoplot.crs中的对象
- hue:当需要根据df中的某列或外部的其他序列数据来映射散点的色彩时,可传入对应df中指定列名或外部序列数据,默认为None即不进行设色
- cmap:和matplotlib中的cmap使用方式一致,用于控制色彩映射方案
- scheme:作用类似geopandas中的scheme参数,用于控制分层设色,详见本系列文章的分层设色篇,但不同的是在geoplot0.4.0版本之后此参数不再搭配分层数量k共同使用,而是更新为传入mapclassify分段结果对象,下文中会做具体演示
- scale:用于设定映射散点大小的序列数据,格式同hue,默认为None即每个散点等大小
- limits:元组型,当scale不为None时,用于设定散点大小尺寸范围,格式为(min, max)
- s:当scale设置为None时,用于控制散点的尺寸大小
- color:当hue设置为None时,用于控制散点的填充色彩
- marker:用于设定散点的形状
- alpha:控制全局色彩透明度
- linewidths:控制散点轮廓宽度
- edgecolors:控制散点轮廓颜色
- legend:bool型,用于控制是否显示图例
- legend_var:传入’hue’或scale,当设定为hue时图例显示色彩映射信息,当设定为’scale’时图例显示大小映射信息
- legend_values:list型,用于自定义图例显示的各个具体数值
- legend_labels:list型,用于自定义图例显示的各个具体数值对应的文字标签,与legend_values搭配使用
- legend_kwargs:字典,在legend参数设置为True时来传入更多微调图例属性的参数
- extent:元组型,用于传入左下角和右上角经纬度信息来设置地图空间范围,格式为(min_longitude, min_latitude,
max_longitude, max_latitude) - figsize:元组型,用于控制画幅大小,格式为(x, y)
- ax:matplotlib坐标轴对象,如果需要在同一个坐标轴内叠加多个图层就需要用这个参数传入先前待叠加的ax
知晓了上述主要参数之后,下面我们通过实际案例来学习修改各个参数得到的效果,使用到的数据为波士顿区划面数据以及波士顿部分地区Airbnb房源点数据:
boston_zip_codes = gpd.read_file('geometry/boston-zip-codes.geojson')
boston_zip_codes.head()
boston_airbnb_listings = gpd.read_file('geometry/boston-airbnb-listings.geojson')
boston_airbnb_listings.head()
- 普通散点分布
首先我们来简单绘制房源分布散点图,对大小、色彩、透明度等基础属性进行简单调整:
# 简单绘制波士顿行政区划
ax = gplt.polyplot(df=boston_zip_codes,
projection=gcrs.AlbersEqualArea(),
edgecolor='lightgrey',
linewidths=0.5)
gplt.pointplot(df=boston_airbnb_listings,
ax=ax, # 叠加图层
s=1,
linewidths=0.1,
color='grey',
alpha=0.4)
plt.savefig("图8.png", bbox_inches='tight', pad_inches=0, dpi=300)
通过这样一张简单的图我们是看不出太多信息的,只能大致看出哪些地方房源分布较多。
- 映射房源价格到色彩上
将房源价格列作为色彩映射列,使用mapclassify中的分位数法将价格区间等分成五段,并使用其他的视觉参数和自定义图例参数:
import mapclassify as mc
#解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 简单绘制波士顿行政区划
ax = gplt.polyplot(df=boston_zip_codes,
projection=gcrs.AlbersEqualArea(),
edgecolor='lightgrey',
linewidths=0.5)
scheme = mc.Quantiles(boston_airbnb_listings['price'], k=5)
gplt.pointplot(df=boston_airbnb_listings,
ax=ax, # 叠加图层
s=1, # 散点大小
linewidths=0.1, # 散点轮廓宽度
hue='price', # 以price作为色彩映射列
cmap='Reds', # 色彩方案为Reds
scheme=scheme, # 传入mapclassify对象
legend=True, # 开启图例
legend_kwargs={
'loc': 'lower right', # 图例位置
'title': '价格区间', # 图例标题
'title_fontsize': 8, # 图例标题字体大小
'fontsize': 6, # 图例非标题外字体大小
'shadow': True, # 添加图例阴影
},
legend_labels=['80%-100%价格房源',
'60%-80%价格房源',
'40%-60%价格房源',
'20%-40%价格房源',
'前20%价格房源'])
plt.savefig("图9.png", bbox_inches=