我们来简单看看创建出的网格是什么样子的,配合contextily添加上在线底图:
import matplotlib.pyplot as plt import contextily as ctx fig, ax = plt.subplots(figsize=(4, 4), dpi=200) ax = manhattan_grids.plot(facecolor='none', edgecolor='black', ax=ax) # 标注每个网格的id for row in manhattan_grids.itertuples(): centroid = row.geometry.centroid ax.text(centroid.x, centroid.y, row.id, ha='center', va='center') # 关闭坐标轴 ax.axis('off') # 添加carto的素色底图 ctx.add_basemap(ax, source='https://d.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', zoom=12) fig.savefig('图7.png', dpi=300, bbox_inches='tight', pad_inches=0) 图7创建出的网格效果不错~接下来就到了最关键的地方,我们需要计算出在每个原始网格内部上车的全部OD记录,在整个区域中各个网格内的下车点分布情况:
首先我们以某个网格为例,介绍如何为其关联上车点、下车点以信息,并利用简单的仿射变换得到镶嵌在其内部的小网格。
以id=21的网格为例,对应着肯尼迪国际机场的区域,首先我们利用id对应的从manhattan_grids表中提取的网格面数据,基于空间连接来与od_points表进行关联,从而匹配到目标网格内对应原始od信息表中的所有上车点记录;
接着根据这些记录对应的下车点信息与od_points表进行匹配,从而得到所有下车点矢量信息,然后再次利用空间连接,得到所需的网格下车点分布结果:
i = 21 # 对应肯尼迪国际机场的网格 # 计算得到所有网格整体的重心坐标 center_grid = (manhattan_grids.unary_union.centroid.x, manhattan_grids.unary_union.centroid.y) # 提取对应下车点坐标 dropoff = ( # 利用空间连接,提取目标网格中包含到的所有坐标点 gpd .sjoin(manhattan_grids.loc[i:i, :], right_df=od_points, op='contains') [['lng', 'lat', 'geometry']] # 利用提取到的坐标点信息,关联在目标 # 网格中上车的记录对应的下车点坐标 .merge(taxi_trip_flow[['pickup_longitude', 'pickup_latitude', 'dropoff_longitude', 'dropoff_latitude']], left_on=['lng', 'lat'], right_on=['pickup_longitude', 'pickup_latitude']) [['dropoff_longitude', 'dropoff_latitude']] # 根据匹配到的下车点坐标 # 与od_points表进行连接 # 找到对应下车点的矢量信息 .merge(od_points, left_on=['dropoff_longitude', 'dropoff_latitude'], right_on=['lng', 'lat'])[['geometry']] ) # 提取上一步得到的下车坐标点在各个网格中的分布数据 grid_distrib = ( # 利用空间连接匹配网格与下车坐标点 gpd .sjoin(manhattan_grids, # 转换为同一坐标参考系的GeoDataFrame gpd.GeoDataFrame(dropoff, crs='EPSG:3857'), op='contains') # 根据网格id进行分组计数 .groupby('id', as_index=False) .agg({'index_right': 'count'}) .rename(columns={'index_right': '下车记录数'}) ) grid_distrib.head() 图8接着我们将上述的统计结果按照id列与原始网格表进行关联,并利用仿射变换得到整体网格向目标网格内部的缩小镶嵌结果(思路是首先将原始网格整体移动到与目标网格重心重合,接着按照x和y方向上的比例进行缩小),为了方便之后绘图标记出目标网格对应的镶嵌小网格位置,最后还需添加是否为目标网格列信息:
# 利用基本的仿射变换得到原始网格向对应目标网格的嵌入变换 # 获取当前目标网格的重心坐标 center_child_grid = (manhattan_grids.at[i, 'geometry'].centroid.x, manhattan_grids.at[i, 'geometry'].centroid.y) # 利用仿射变换得到整体网格在目标网格中的镶嵌 draw_gdf = ( manhattan_grids # 基于原始的网格矢量来更新放缩后的网格矢量 .assign(geometry=manhattan_grids # 第一步:将原始网格的重心平移到目标网格的重心上 .translate(center_child_grid[0]-center_grid[0], center_child_grid[1]-center_grid[1]) # 第二步:以目标网格的重心为缩放中心,进行 .scale(xfact=1 / 5, yfact=1 / 5, origin=(manhattan_grids.at[i, 'geometry'].centroid.x, manhattan_grids.at[i, 'geometry'].centroid.y))) .merge(grid_distrib, on='id', how='left') .assign(是否为目标网格=0) ) draw_gdf.loc[draw_gdf.id == i, '是否为目标网格'] = 1 draw_gdf.head() 图9