ArcGIS处理数据太慢?GeoPandas高效分析实战(附:完整源码)
引言
《ArcGIS处理数据太慢?GeoPandas高效分析实战(附:完整源码)》这篇教程,专门解决一个很常见的问题:同样是缓冲区、叠加、空间连接、字段统计,为什么在 ArcGIS 里处理几十万条要素会越来越慢,而用 Python 和 GeoPandas 可以更适合批量分析与自动化处理。
本文不会简单说“GeoPandas一定比ArcGIS快”。更准确的说法是:当你的任务属于批量、重复、规则明确的矢量空间分析时,GeoPandas可以减少手工操作、避免界面等待,并且更容易把数据清洗、空间分析和结果导出串成一个可复用流程。
本文示例以一个典型场景为主:已有一批点位数据和行政区面数据,需要完成坐标系统一、空间连接、按行政区统计点数量,并导出结果。这个流程在 ArcGIS Pro 中可以做,但如果每天、每周都要重复,GeoPandas更适合写成脚本。

背景
很多GIS同学遇到“ArcGIS处理数据太慢”,并不是因为软件本身不能处理,而是任务类型不适合一直靠手工界面完成。尤其是以下几类工作,ArcGIS Pro 或 ArcMap 中频繁点击工具、等待进度条、反复检查参数,很容易消耗大量时间。
- 同一套空间分析流程需要对多个城市、多个年份、多个图层重复执行。
- 数据量较大,例如几十万点、上百万线段、复杂行政区面。
- 每次处理前都要做字段清洗、坐标系检查、空几何过滤、重复值删除。
- 分析结果还要继续做统计汇总、表格导出、字段重命名。
- 团队需要可复现流程,而不是依赖某个人的手工操作记录。
GeoPandas是Python生态中的矢量GIS分析库,可以理解为“带几何字段的Pandas”。它适合处理 Shapefile、GeoPackage、GeoJSON、PostGIS 等常见GIS数据,并能与 Shapely、Pyogrio、Fiona、PyProj、Rtree 或 PyGEOS/Shapely 2.x 等库配合完成空间分析。
如果你的需求是制图排版、复杂编辑、影像可视化、交互检查,ArcGIS仍然很强。但如果你的需求是批量数据处理、自动化空间统计、重复分析流程,GeoPandas高效分析会更有优势。
原理
要判断一个任务是否适合从 ArcGIS 转到 GeoPandas,先要理解性能瓶颈通常来自哪里。
1. 界面操作慢,不等于算法一定慢
ArcGIS中的很多工具本身很成熟,但手工使用时会产生额外成本,例如打开工程、加载图层、选择输入输出、设置字段、写临时文件、等待界面刷新。单次操作问题不大,但重复上百次时,界面成本会被放大。
2. GeoPandas适合把流程写成代码
GeoPandas的核心优势不是“按钮更少”,而是可以把一整套处理过程写成可重复运行的脚本。只要输入数据路径不变,或者用配置参数控制路径,就能自动完成处理。
3. 空间索引决定空间连接效率
在做空间连接、相交判断、最近邻分析时,如果没有空间索引,程序可能需要进行大量几何两两比较。GeoPandas在执行 sjoin 等操作时会使用空间索引来减少候选几何数量,从而提升效率。
4. 坐标系会直接影响结果和速度
经纬度坐标系适合表达位置,但不适合直接计算面积、距离和缓冲区。对于GeoPandas高效分析,建议先统一坐标系,并在需要距离或面积计算时转换到合适的投影坐标系。
一句话原则:ArcGIS适合交互式GIS工作,GeoPandas适合可重复、可批量、可审计的矢量数据分析流程。
步骤
下面给出一个完整实战流程:读取点数据和行政区面数据,统一坐标系,做空间连接,按行政区统计点数量,并输出结果文件。这个案例可以替代很多在 ArcGIS 中反复执行“空间连接 + 汇总统计”的工作。
步骤1:准备Python环境
建议使用独立环境安装GeoPandas,避免和已有ArcGIS Python环境混在一起。推荐使用 conda 或 mamba。
conda create -n gis-geopandas python=3.11 -y
conda activate gis-geopandas
conda install -c conda-forge geopandas pyogrio openpyxl -y
如果你更习惯 pip,也可以使用:
python -m venv .venv
.venvScriptsactivate
pip install geopandas pyogrio openpyxl
在Windows环境下,GIS相关库涉及GDAL、PROJ等依赖。初学者优先推荐 conda-forge,因为它会自动处理大部分底层依赖。
步骤2:准备输入数据
本文假设有两个输入数据:
- 点数据:
data/poi.gpkg,图层名为poi,表示兴趣点、监测点或事件点。 - 行政区面:
data/admin.gpkg,图层名为admin,包含字段name表示行政区名称。
如果你的数据是 Shapefile,也可以读取 .shp 文件。但在批量处理时,更建议使用 GeoPackage,因为它对中文字段、长字段名和多图层管理更友好。
步骤3:读取数据并检查基本信息
import geopandas as gpd
from pathlib import Path
base_dir = Path("data")
poi_path = base_dir / "poi.gpkg"
admin_path = base_dir / "admin.gpkg"
poi = gpd.read_file(poi_path, layer="poi", engine="pyogrio")
admin = gpd.read_file(admin_path, layer="admin", engine="pyogrio")
print("POI数量:", len(poi))
print("行政区数量:", len(admin))
print("POI坐标系:", poi.crs)
print("行政区坐标系:", admin.crs)
print("POI字段:", poi.columns.tolist())
print("行政区字段:", admin.columns.tolist())
这一步非常重要。很多所谓“ArcGIS处理数据太慢”或“空间连接结果不对”,其实是因为坐标系为空、字段名不一致、几何无效或数据中混入了空几何。
步骤4:清理空几何和无效几何
poi = poi[poi.geometry.notna()].copy()
admin = admin[admin.geometry.notna()].copy()
poi = poi[~poi.geometry.is_empty].copy()
admin = admin[~admin.geometry.is_empty].copy()
admin["geometry"] = admin.geometry.make_valid()
print("清理后POI数量:", len(poi))
print("清理后行政区数量:", len(admin))
make_valid 用于修复部分无效面几何,例如自相交、多边形环错误等。如果面数据来自第三方或历史数据,建议在空间连接前先做这一步。
步骤5:统一坐标系
空间连接要求两个图层在同一坐标参考系统中。否则即使程序可以运行,结果也可能完全错误。
if poi.crs is None:
raise ValueError("POI数据缺少坐标系,请先定义正确CRS。")
if admin.crs is None:
raise ValueError("行政区数据缺少坐标系,请先定义正确CRS。")
if poi.crs != admin.crs:
poi = poi.to_crs(admin.crs)
print("统一后的POI坐标系:", poi.crs)
print("行政区坐标系:", admin.crs)
注意:to_crs 是坐标转换,不是“定义投影”。如果原始数据本身没有正确CRS,不能随便用 to_crs,必须先确认它原来到底是什么坐标系。
步骤6:执行空间连接
这里使用 gpd.sjoin,判断每个点落在哪个行政区面内。常见谓词包括 within、intersects、contains。对于点落面统计,通常使用 within。
joined = gpd.sjoin(
poi,
admin[["name", "geometry"]],
how="left",
predicate="within"
)
print(joined.head())
print("连接后记录数:", len(joined))
print("未匹配行政区的点数量:", joined["name"].isna().sum())
如果发现大量点没有匹配行政区,优先检查三件事:坐标系是否一致、点是否落在行政区范围外、行政区面是否存在缝隙或边界错误。
步骤7:按行政区统计点数量
stat = (
joined
.groupby("name", dropna=False)
.size()
.reset_index(name="poi_count")
)
stat["name"] = stat["name"].fillna("未匹配行政区")
print(stat.sort_values("poi_count", ascending=False).head(10))
这一步相当于在 ArcGIS 中做空间连接后,再做汇总统计。用GeoPandas写成脚本后,可以很方便地嵌入到日报、周报或批量质检流程中。
步骤8:把统计结果回写到行政区面
admin_result = admin.merge(
stat[stat["name"] != "未匹配行政区"],
on="name",
how="left"
)
admin_result["poi_count"] = admin_result["poi_count"].fillna(0).astype(int)
print(admin_result[["name", "poi_count"]].head())
回写后的行政区面可以直接用于分级设色制图,也可以继续在 QGIS、ArcGIS Pro 或 WebGIS 中展示。
步骤9:导出GeoPackage和Excel结果
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)
admin_result.to_file(
output_dir / "admin_poi_count.gpkg",
layer="admin_poi_count",
driver="GPKG"
)
stat.to_excel(
output_dir / "poi_count_by_admin.xlsx",
index=False
)
print("处理完成:")
print(output_dir / "admin_poi_count.gpkg")
print(output_dir / "poi_count_by_admin.xlsx")
GeoPackage适合保存空间结果,Excel适合给非GIS同事查看统计表。如果要继续进入PostGIS,也可以使用 to_postgis,但需要额外配置数据库连接。
完整源码
import geopandas as gpd
from pathlib import Path
def main():
base_dir = Path("data")
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)
poi_path = base_dir / "poi.gpkg"
admin_path = base_dir / "admin.gpkg"
poi = gpd.read_file(poi_path, layer="poi", engine="pyogrio")
admin = gpd.read_file(admin_path, layer="admin", engine="pyogrio")
print("POI数量:", len(poi))
print("行政区数量:", len(admin))
print("POI坐标系:", poi.crs)
print("行政区坐标系:", admin.crs)
poi = poi[poi.geometry.notna()].copy()
admin = admin[admin.geometry.notna()].copy()
poi = poi[~poi.geometry.is_empty].copy()
admin = admin[~admin.geometry.is_empty].copy()
admin["geometry"] = admin.geometry.make_valid()
if poi.crs is None:
raise ValueError("POI数据缺少坐标系,请先定义正确CRS。")
if admin.crs is None:
raise ValueError("行政区数据缺少坐标系,请先定义正确CRS。")
if poi.crs != admin.crs:
poi = poi.to_crs(admin.crs)
joined = gpd.sjoin(
poi,
admin[["name", "geometry"]],
how="left",
predicate="within"
)
unmatched_count = joined["name"].isna().sum()
print("未匹配行政区的点数量:", unmatched_count)
stat = (
joined
.groupby("name", dropna=False)
.size()
.reset_index(name="poi_count")
)
stat["name"] = stat["name"].fillna("未匹配行政区")
admin_stat = stat[stat["name"] != "未匹配行政区"].copy()
admin_result = admin.merge(
admin_stat,
on="name",
how="left"
)
admin_result["poi_count"] = admin_result["poi_count"].fillna(0).astype(int)
admin_result.to_file(
output_dir / "admin_poi_count.gpkg",
layer="admin_poi_count",
driver="GPKG"
)
stat.to_excel(
output_dir / "poi_count_by_admin.xlsx",
index=False
)
print("处理完成。")
print("空间结果:", output_dir / "admin_poi_count.gpkg")
print("统计表:", output_dir / "poi_count_by_admin.xlsx")
if __name__ == "__main__":
main()
常见坑
1. 坐标系看起来一样,实际EPSG不同
很多数据都显示为 WGS 84,但有的数据是 EPSG:4326,有的数据可能是被错误定义的投影坐标。不要只看图层能否叠在一起,要检查 gdf.crs,必要时回到数据来源确认原始坐标系。
2. 用经纬度直接做距离和缓冲区
如果你要做缓冲区、距离筛选、面积统计,不建议在 EPSG:4326 这类经纬度坐标系下直接计算。应先转换到适合当地的投影坐标系,例如高斯克吕格、UTM或地方投影。
3. Shapefile字段名被截断
Shapefile字段名长度有限,中文编码也容易出问题。GeoPandas处理批量数据时,建议优先使用 GeoPackage,减少字段截断和编码错误。
4. 空间连接结果重复
如果一个点落在多个面中,或者行政区面存在重叠,sjoin 会产生多条匹配记录。此时不要急着认为GeoPandas错了,应检查面数据是否重叠,或者业务上是否允许一对多关系。
5. 数据太大时内存不足
GeoPandas主要在内存中处理数据。如果数据达到千万级要素,单机内存可能成为瓶颈。可以考虑分块处理、先做空间范围裁剪、使用PostGIS,或者使用Dask-GeoPandas等并行方案。
6. ArcGIS和GeoPandas结果边界不完全一致
不同软件底层几何引擎、容差处理、边界谓词可能存在差异。对于边界点,within、contains、intersects 的结果可能不同。需要根据业务定义选择合适的空间关系。
方法比较
| 方法 | 适合场景 | 优点 | 限制 |
|---|---|---|---|
| ArcGIS Pro手工工具 | 一次性分析、交互检查、制图输出 | 界面友好,工具体系完整,适合可视化检查 | 重复任务效率低,参数容易手工设错 |
| ArcPy脚本 | ArcGIS体系内自动化处理 | 兼容ArcGIS工具箱和地理数据库能力 | 依赖ArcGIS许可和环境,跨平台不如开源生态灵活 |
| GeoPandas脚本 | 批量矢量分析、空间连接、字段统计、格式转换 | 代码简洁,易与Pandas结合,适合自动化流程 | 超大数据受内存限制,复杂编辑和制图不如桌面GIS直观 |
| PostGIS | 多人共享、千万级数据、服务端空间查询 | 空间索引强,适合数据库级管理和WebGIS后台 | 需要数据库维护能力,初学成本高于本地脚本 |
如果只是偶尔处理一个图层,ArcGIS Pro很方便。如果你正在反复执行同一类空间连接、裁剪、汇总统计,GeoPandas高效分析更值得投入学习。如果数据已经进入数据库并服务于WebGIS,PostGIS通常更合适。
检查清单
在把“ArcGIS处理数据太慢”的流程迁移到GeoPandas之前,可以按下面清单逐项检查。
- 数据格式:优先使用 GeoPackage,避免Shapefile字段名和编码问题。
- 坐标系:所有输入图层必须有正确CRS,空间分析前保持一致。
- 几何质量:过滤空几何,修复无效面,检查是否存在重叠面或缝隙。
- 字段名称:提前确认用于关联和统计的字段,例如
name、code、type。 - 空间关系:点落面统计常用
within,边界也要算入时可评估intersects。 - 性能瓶颈:如果空间连接慢,先检查数据范围、要素数量、空间索引和几何复杂度。
- 结果验证:抽样对比ArcGIS结果,重点检查未匹配点、边界点和统计总数。
- 输出格式:空间结果导出GPKG,统计表导出XLSX或CSV,便于后续使用。
FAQ
ArcGIS处理数据太慢,一定要换GeoPandas吗?
不一定。如果你只是偶尔做一次分析,ArcGIS Pro的图形界面更直观。如果你需要重复处理、多批数据、自动汇总和导出,GeoPandas更适合把流程脚本化。
GeoPandas高效分析是否能完全替代ArcGIS?
不能简单替代。GeoPandas适合矢量数据处理、空间连接、字段统计和自动化流程;ArcGIS在交互编辑、地图制图、企业GIS平台和部分高级分析工具方面仍然有优势。
为什么GeoPandas空间连接结果和ArcGIS空间连接结果不同?
常见原因包括坐标系不同、几何无效、面边界重叠、空间谓词选择不同,以及边界点处理规则不同。建议先统一CRS,再抽样检查边界点和未匹配点。
GeoPandas处理百万级数据会不会很慢?
取决于数据类型、几何复杂度、内存大小和分析方法。百万级点落面统计通常可以尝试GeoPandas,但如果是复杂面叠加或千万级数据,建议考虑PostGIS、分块处理或先简化几何。
已有Shapefile数据,可以直接用于本文代码吗?
可以,把 gpd.read_file 的路径改成 .shp 文件即可。但如果字段较多、中文字段较多或需要长期维护,建议先转换为GeoPackage。
ArcPy和GeoPandas应该学哪个?
如果你的工作高度依赖ArcGIS许可、地理数据库和工具箱,ArcPy很有价值。如果你希望做开源GIS分析、批量数据处理、WebGIS后台数据预处理,GeoPandas更灵活。两者并不冲突。
结论
当你觉得ArcGIS处理数据太慢时,先不要急着换软件,而要判断任务是否属于重复性、批量化、规则明确的矢量分析。如果是,GeoPandas高效分析可以把原本依赖手工点击的空间连接、统计汇总、结果导出,整理成一段可复用脚本。
本文给出的完整源码覆盖了读取数据、清理几何、统一坐标系、空间连接、分组统计和导出结果几个关键环节。实际项目中,你可以在此基础上继续加入字段标准化、批量遍历文件夹、日志记录、异常捕获和结果质检,让GIS数据处理流程更稳定、更可复现。
对GIS初学者来说,最实用的学习路径是:先用ArcGIS理解空间分析逻辑,再用GeoPandas把重复流程自动化。这样既不会脱离GIS原理,也能显著提升日常数据处理效率。