接空间数据统计分析与可视化(1)
一、空间数据的读取和预处理
(1)读取和加载地理数据文件
1. 核心工具与核心逻辑
- 主要库:GeoPandas(兼容多种主流地理数据格式,操作简洁);
- 核心逻辑:通过 GeoPandas 的
read_file()方法读取文件,自动将地理数据转换为GeoDataFrame(融合几何对象与属性数据的结构),直接支持后续分析。
2. 常见格式与读取方法
-
重点格式:Shapefile(最常用矢量格式,存储点 / 线 / 面)
-
代码示例:
pythonimport geopandas as gpd # 传入文件完整路径(注意路径分隔符用"/"或"\") gdf = gpd.read_file('文件路径.shp') # 后缀为.shp,无需额外配置
-
-
其他支持格式:GeoJSON、GPKG(GeoPackage)、SHPX(Shapefile 索引文件)、KML 等
- 读取方式统一:仅需修改
read_file()的文件路径(带对应格式后缀,如'数据.geojson'、'数据.gpkg'),无需更换方法。
- 读取方式统一:仅需修改
(2)数据预处理
一、数据清理和去重
目的 :去除重复、异常数据,保证数据准确性。核心操作:
- 删除重复数据 :用
drop_duplicates()移除完全重复的记录(或按指定列去重); - 处理异常值:通过布尔索引筛选掉不合理数据(如面积≤0 的多边形);
- 保存结果 :用
to_file()存储清理后的数据。
示例代码:
python
import geopandas as gpd
gdf = gpd.read_file("数据路径.shp") # 读数据
gdf = gdf.drop_duplicates() # 去重
gdf = gdf[gdf["shape_area"] > 0] # 删异常值
gdf.to_file("清理后数据路径.shp") # 保存
二、处理缺失数据
目的 :补全或移除缺失值,避免分析偏差。核心操作:
- 填充缺失值 :用
fillna()填充数值(如均值、中位数)或分类值(如众数); - 删除缺失值 :用
dropna(subset=列名)移除关键属性(如名称、坐标)缺失的记录; - 保存结果 :用
to_file()存储处理后的数据。
示例代码:
python
gdf = gpd.read_file("数据路径.shp")
mean_area = gdf["shape_area"].mean()
gdf["shape_area"] = gdf["shape_area"].fillna(mean_area) # 填充
gdf = gdf.dropna(subset=["ntaname"]) # 删除关键列缺失值
gdf.to_file("处理后数据路径.shp")
三、坐标系转换
目的 :统一不同数据源的坐标系,确保空间分析对齐。核心操作:
- 查看原坐标系 :通过
gdf.crs获取当前坐标参考系统(CRS); - 转换坐标系 :用
to_crs(目标EPSG码)转换(如 WGS84 对应EPSG:4326); - 验证并保存 :检查转换后 CRS,用
to_file()存储。
示例代码:
python
gdf = gpd.read_file("数据路径.shp")
print("原坐标系:", gdf.crs)
gdf = gdf.to_crs("EPSG:4326") # 转换到WGS84
print("新坐标系:", gdf.crs)
gdf.to_file("转换后数据路径.shp"
二、空间数据的统计分析
1. 空间连接
空间连接是通过 GeoPandas 将两个(或多个)数据集(含地理数据 + 属性数据)按 "属性关联" 或 "空间关系" 合并,实现数据整合与属性传递,是 地理信息系统(GIS) 分析的核心操作。
(1)属性连接(用户示例类型):按共同属性列匹配
- 适用场景:两个数据集有相同标识列(如编码、名称),无需空间关系判断。
- 核心方法:
GeoDataFrame.merge()(兼容 Pandas 的 merge 逻辑)。
-
关键参数:
left_on:左数据集(地理数据 gdf)的连接列;right_on:右数据集(普通数据 df)的连接列;how:连接方式(left左连接、inner内连接、outer外连接,常用left保留所有地理数据)。- 不知道左右内连接什么意思可以看这篇文章
-
示例代码:
pythonimport geopandas as gpd import pandas as pd # 1. 读数据:地理数据(gdf)+ 普通属性数据(df) gdf = gpd.read_file("地块数据.shp") # 含地理几何列(geometry)和属性列(如ntacode) pop_df = pd.read_csv("人口数据.csv") # 普通表格,含连接列(如NTA Code) # 2. 数据预处理(可选):筛选目标数据(如2010年人口) pop_df = pop_df[pop_df["Year"] == 2010] # 3. 按属性连接:通过"ntacode"和"NTA Code"匹配 merged_gdf = gdf.merge(pop_df, left_on="ntacode", right_on="NTA Code", how="left")
(2) 空间连接(按空间关系匹配):核心 GIS 连接方式
- 适用场景:无共同属性列,按几何对象的空间关系关联(如 "点在多边形内""线穿过多边形")。
- 核心方法:
gpd.sjoin()(专门的空间连接函数)。
-
关键参数:
left_df/right_df:待连接的两个 GeoDataFrame(均需含 geometry 列);predicate:空间关系(within含于、contains包含、intersects相交等);how:连接方式(同属性连接)。
-
示例代码(点 - 多边形空间连接):
python# 假设:点数据(居民点)、多边形数据(行政区) points_gdf = gpd.read_file("居民点.shp") poly_gdf = gpd.read_file("行政区.shp") # 空间连接:将每个居民点关联到其所在的行政区(传递行政区属性) spatial_merged_gdf = gpd.sjoin(points_gdf, poly_gdf, predicate="within", how="left")
关键步骤(通用流程)
- 读取数据:地理数据(gdf)+ 待关联数据(gdf 或普通 df);
- 数据预处理:筛选目标数据、统一坐标系(空间连接必需);
- 执行连接:属性连接用
merge(),空间连接用sjoin(); - 后续分析:基于合并后的数据做统计(如按地块统计人口)、可视化等。
核心要点
- 空间连接前需确保两个 GeoDataFrame 坐标系一致(用
gdf.to_crs()统一); - 属性连接需保证连接列格式一致(如编码均为字符串 / 数值);
- 连接后需检查数据完整性(如
merged_gdf.isnull().sum()查看缺失关联)。
2. 空间缓冲区分
空间缓冲区分析的核心是为地理对象(点、线、面)创建 "影响范围"(如地铁站 1000 米服务圈),通过 GeoPandas 实现,关键步骤和函数如下:
一、核心流程与函数用法
(1)读取地理数据(获取分析对象)
目的:加载包含地理坐标的原始数据(如地铁站点数据)。
函数 :
geopandas.read_file(filename)
-
参数 :
filename(必填):地理数据文件路径(支持 Shapefile、GeoJSON 等格式)。 -
示例:
pythonimport geopandas as gpd # 读取地铁站Shapefile数据 subway_stations = gpd.read_file('D:/数据/Subway Stations/geo_export_abaf55bb.shp') -
说明 :返回
GeoDataFrame,包含geometry列(存储点 / 线 / 面坐标)和属性列(如站点名称)。
(2) 转换坐标系(确保距离单位有效)
目的:将数据从 "地理坐标系(经纬度,单位:度)" 转换为 "投影坐标系(单位:米 / 千米)",否则缓冲区距离会失真。
函数 :
GeoDataFrame.to_crs(crs)
-
参数 :
crs(必填):目标坐标系的 EPSG 码(如"EPSG:2163"为美国等距圆锥投影,单位:米)。 -
示例:
pythontarget_crs = 'EPSG:2163' # 选择适合分析区域的投影坐标系 subway_stations = subway_stations.to_crs(target_crs) # 转换坐标系 -
关键:
- 地理坐标系(如
EPSG:4326)的 "度" 无法直接表示实际距离(1 度≈111 千米),必须转换为投影坐标系; - 不同地区需匹配对应投影(如中国常用
EPSG:32649,UTM 分区投影,单位:米)。
- 地理坐标系(如
(3) 创建缓冲区(核心操作)
目的:为每个地理对象生成指定距离的 "影响范围"(圆形 / 多边形)。
函数 :
GeoSeries.buffer(distance)
-
参数:
distance(必填):缓冲区半径,单位与当前坐标系一致(如投影坐标系下为 "米");resolution(可选):缓冲区边缘平滑度(默认 16,值越大越接近圆形)。
-
示例:
pythonbuffer_radius = 1000 # 缓冲区半径1000米(单位由坐标系决定) # 为每个地铁站的点坐标创建缓冲区,结果存到新列"buffer"中 subway_stations['buffer'] = subway_stations['geometry'].buffer(buffer_radius) -
说明:
- 点要素→生成圆形缓冲区;
- 线要素→生成 "管道状" 缓冲区(沿线路两侧扩展);
- 面要素→生成 "环状" 缓冲区(沿边界向外 / 向内扩展)。
(4)可视化结果(直观展示缓冲区)
目的:绘制原地理对象和缓冲区,验证分析结果。
核心函数:
GeoDataFrame.plot(ax, color, markersize, alpha, label):绘制地理数据;
matplotlib.pyplot辅助函数:创建画布、添加图例、显示图像。
-
示例:
pythonimport matplotlib.pyplot as plt # 创建画布和坐标轴 fig, ax = plt.subplots() # 绘制原地铁站点(蓝色小点) subway_stations.plot(ax=ax, color='blue', markersize=5, label='地铁站') # 绘制缓冲区(橙色半透明多边形) subway_stations['buffer'].plot(ax=ax, color='orange', alpha=0.5, label='1000米缓冲区') ax.set_aspect('equal') # 保持地图比例(避免拉伸变形) plt.legend() # 显示图例 plt.show() # 展示图像
二、关键注意事项
- 坐标系是核心前提:缓冲区的 "距离"(如 1000 米)必须依赖投影坐标系,否则结果无实际意义;
buffer()参数与对象匹配:半径单位需与坐标系一致,且根据要素类型(点 / 线 / 面)生成不同形状的缓冲区;- 可视化比例 :
ax.set_aspect('equal')确保缓冲区形状正确(避免圆形被拉伸为椭圆)。
3. 空间数据的聚合和汇总
空间数据的聚合和汇总核心是按 "分组条件" 对地理数据的属性或几何形状进行合并 / 计算,分为 "属性聚合"(统计数值)和 "几何聚合"(合并形状)两类,示例主要展示属性聚合,以下是详细用法:
一、核心目的
将分散的空间数据按某一分类标准(如行政区、类型)合并,同时计算该组的统计量(如总面积、平均人口)或合并几何形状(如将多个社区合并为一个行政区),用于宏观分析(如 "按城市汇总下属区域的面积")。
二、属性聚合
作用 :按分类字段(如boro_name,行政区名称)对数值属性(如shape_area,面积)进行汇总计算(求和、均值等)。
步骤与代码解析
-
读取空间数据 :获取包含分类字段和待聚合属性的
GeoDataFrame。pythonimport geopandas as gpd # 读取地块数据(含'boro_name'分类字段和'shape_area'面积属性) gdf = gpd.read_file('地块数据.shp') -
按分类字段分组 :用
groupby(分组字段)指定聚合的 "分组依据"(如按boro_name分组,即按行政区分组)。 -
选择属性并应用聚合函数 :对分组后的数值属性(如
shape_area)使用聚合函数(sum求和、mean均值、count计数等)。python# 按'boro_name'分组,对'shape_area'求和(计算每个行政区的总面积) gdf_area = gdf.groupby('boro_name')['shape_area'].sum().reset_index()groupby('boro_name'):按行政区名称分组;['shape_area']:指定要聚合的属性(面积);.sum():聚合函数(求和,计算每个组的总面积);.reset_index():将分组结果转换为普通DataFrame(便于查看和后续处理)。
-
查看结果:打印或使用聚合后的统计数据。
pythonprint(gdf_area.head()) # 显示前几行结果(每个行政区及其总面积)
三、几何聚合
作用:将同一组的几何对象(如多个社区多边形)合并为一个整体几何形状(如行政区多边形),同时可保留属性聚合结果。
核心函数 :GeoDataFrame.dissolve(by=分组字段, aggfunc=聚合函数)
by:指定分组字段(如boro_name);aggfunc:对属性的聚合函数(如sum,可选)。
示例:
python
# 按'boro_name'合并几何形状,并计算每个行政区的总面积
gdf_dissolved = gdf.dissolve(by='boro_name', aggfunc={'shape_area': 'sum'})
# 结果:每个行政区一行,geometry列为合并后的多边形,shape_area为总面积
四、关键要点
-
分组字段选择:需是分类属性(如行政区名称、地块类型),确保同一组的对象有逻辑关联;
-
聚合函数匹配:根据需求选择函数(求和用于总量,均值用于平均水平,计数用于数量);
-
属性聚合 vs 几何聚合:
- 仅需统计数值:用
groupby(示例方法); - 需合并几何形状:用
dissolve(同时可包含属性聚合)。
- 仅需统计数值:用
二、空间数据可视化
空间数据可视化的核心是通过 GeoPandas 结合 Matplotlib,将地理数据(点、线、面)以地图形式展示,并通过布局优化(图例、标签等)增强可读性,最终可保存为多种格式。以下是分场景的用法总结:
1.基础地图可视化(GeoPandas 核心绘图)
目的:快速绘制地理数据的基础地图,展示几何形状分布。
核心步骤与函数
读取数据 :用
gpd.read_file()加载地理数据(如 Shapefile),得到GeoDataFrame。绘制地图 :用
GeoDataFrame.plot()直接绘制,默认显示几何形状。显示图像 :用
plt.show()展示地图。
示例代码:
python
import geopandas as gpd
import matplotlib.pyplot as plt
# 1. 读取数据
gdf = gpd.read_file("地块数据.shp") # 含geometry列(几何形状)
# 2. 绘制基础地图
ax = gdf.plot() # 返回坐标轴对象,可用于后续优化
# 3. 添加标题并显示
plt.title("基础空间数据可视化")
plt.show()
关键函数:
gdf.plot():基础绘图函数,默认用单一颜色绘制所有几何对象;返回matplotlib.axes.Axes对象,便于后续添加布局元素。
二、地图布局与图例优化(增强可读性)
目的:通过分类着色、添加图例、坐标轴标签、指北针等,让地图更易理解(如按面积大小着色,展示区域差异)。
核心步骤与函数
创建画布与轴 :用
plt.subplots(figsize=(宽, 高))定义地图尺寸,获得fig(画布)和ax(轴)对象。分类着色绘图 :在
gdf.plot()中通过column指定分类字段(如面积),cmap设置颜色映射,legend=True添加图例。添加布局元素 : 标题:
plt.title(); 坐标轴标签:plt.xlabel()(经度)、plt.ylabel()(纬度); 指北针:用ax.annotate()添加箭头标注 "N"。
示例代码:
python
import geopandas as gpd
import matplotlib.pyplot as plt
# 1. 读取数据
gdf = gpd.read_file("地块数据.shp")
# 2. 创建画布(10x8英寸)
fig, ax = plt.subplots(figsize=(10, 8))
# 3. 按"shape_area"(面积)着色,用"coolwarm"色阶,显示图例
gdf.plot(
ax=ax, # 指定绘制到创建的轴上
column="shape_area", # 按面积字段分类
cmap="coolwarm", # 颜色映射(冷到暖,体现大小差异)
legend=True, # 显示图例
legend_kwds={"label": "区域面积"} # 图例标签
)
# 4. 添加布局元素
plt.title("按面积着色的社区地图") # 标题
plt.xlabel("经度") # x轴标签
plt.ylabel("纬度") # y轴标签
# 添加指北针(箭头从下到上,标注"N")
arrowprops = dict(arrowstyle="->", linewidth=1.5, color="black") # 箭头样式
ax.annotate(
"N", # 标注文本
xy=(0.06, 0.95), # 箭头终点(轴坐标系:0-1,右上角为(1,1))
xytext=(0.06, 0.89), # 箭头起点
arrowprops=arrowprops,
ha="center", va="center", # 文本对齐方式
xycoords="axes fraction" # 坐标基于轴比例(而非数据坐标)
)
# 5. 显示地图
plt.show()
关键参数与函数:
column:指定用于分类着色的属性列(如面积、人口),实现 "thematic map(专题图)";cmap:颜色映射方案(如"coolwarm"、"viridis",见 Matplotlib 官方文档);legend_kwds:自定义图例(如标签、位置);ax.annotate():添加文本标注(如指北针),xycoords="axes fraction"确保标注位置不随数据缩放变化。
三、地图输出与保存(持久化结果)
目的:将绘制好的地图保存为图片或文档格式(如 PNG、PDF),便于分享或报告使用。
核心步骤与函数
绘制并优化地图 :完成布局(标题、图例等)后,调用
plt.savefig()保存。指定保存参数:
- 路径与格式:文件名后缀决定格式(
.png、.jpg等);dpi:分辨率(如 300,值越高越清晰);bbox_inches="tight":避免边缘元素(如图例、标题)被裁剪。
示例代码:
python
# (承接上文布局优化后的代码)
# 保存为PNG(高分辨率)
plt.savefig(
"社区面积地图.png", # 路径+文件名
dpi=300, # 分辨率300dpi(适合打印)
bbox_inches="tight" # 紧凑布局,避免裁剪
)
# 保存为PDF(矢量格式,放大不失真)
plt.savefig(
"社区面积地图.pdf",
bbox_inches="tight" # PDF无需指定dpi,默认矢量格式
)
关键说明:
- 保存需在
plt.show()之前调用,否则画布会被清空; - 矢量格式(PDF、SVG)适合编辑(如用 AI 修改),位图格式(PNG、JPG)适合直接展示;
dpi仅对位图有效,建议 300dpi 用于印刷,150dpi 用于屏幕显示。
总结
空间数据可视化的核心流程是:
- 基础绘制 :
read_file()读数据 →plot()绘地图 →show()展示; - 布局优化 :用
subplots()定义尺寸 →column+cmap分类着色 → 添加标题、图例、指北针; - 保存输出 :
savefig()按格式保存,通过dpi和bbox_inches控制质量。