如何在GeoPandas中实现点与多边形的空间连接及解决匹配无返回问题
问题背景
你有两份空间数据:
- 面数据:以WKT字符串格式存储在CSV中,示例如下:
POLYGON((28.56056 77.36535,28.564635293716776 77.3675137204626,28.56871055311656 77.36967760850214,28.572785778190855 77.3718416641586,28.576860968931193 77.37400588747194,28.580936125329096 77.3761702784821,28.585011247376094 77.37833483722912,28.58908633506372 77.38049956375293,28.593161388383457 77.38266445809356,28.59723640732686 77.38482952029099,28.60131139188541 77.38699475038526,28.605386342050664 77.38916014841635,28.60946125781409 77.39132571442434,28.613536139167238 77.39349144844923,28.61761098610158 77.39565735053108,28.62168579860863 77.39782342070995,28.62576057667991 77.39998965902589,28.62983532030691 77.402156065519,28.633910029481108 77.40432264022931,28.637984704194054 77.40648938319696,28.642059344437207 77.408656294462,28.64068221074683 77.41187044231611,28.63920739580329 77.41502778244606,28.63763670052024 77.41812446187686,28.635972042808007 77.42115670220443,28.634215455216115 77.42412080422613,28.63236908243526 77.42701315247152,28.630435178662026 77.42983021962735,28.628416104829583 77.43256857085188,28.626314325707924 77.43522486797251,28.624132406877322 77.437795873562,28.621873011578572 77.44027845488824,28.619538897444272 77.4426695877325,28.617132913115164 77.44496636007166,28.614657994745563 77.44716597562005,28.612117162402576 77.44926575722634,28.609513516363293 77.45126315012166,28.606850233314923 77.45315572501488,28.604130562462267 77.45494118103147,28.60135782154758 77.45661734849246,28.598535392787774 77.45818219153013,28.595666718733966 77.45963381053753,28.592755298058414 77.46097044444889,28.589804681274302 77.46219047284835,28.586818466393503 77.46329241790465,28.583800294527727 77.46427494612952,28.58075384543836 77.46513686995802,28.57768283304089 77.46587714914885,28.574591000868892 77.4664948920035,28.571482117503592 77.46698935640259,28.568359971974488 77.46735995065883,28.565228369136484 77.46760623418534,28.56209112502966 77.4677279179792,28.558952062226695 77.4677248649196,28.55581500517431 77.46759708988064,28.552683775533943 77.46734475965891,28.552683775533943 77.46734475965891,28.553079397193876 77.4622453846313,28.553474828308865 77.45714597129259,28.55387006887434 77.4520465196603,28.554265118885752 77.44694702975198,28.554659978338513 77.4418475015852,28.555054647228083 77.43674793517746,28.555449125549913 77.43164833054634,28.555843413299442 77.42654868770937,28.55623751047213 77.42144900668411,28.556631417063407 77.41634928748812,28.55702513306874 77.41124953013893,28.55741865848359 77.40614973465412,28.557811993303396 77.40104990105122,28.55820513752363 77.39595002934782,28.558598091139757 77.39085011956145,28.558990854147225 77.38575017170969,28.559383426541523 77.3806501858101,28.559775808318093 77.37555016188024,28.560167999472434 77.37045009993768,28.56056 77.36535))
- 点数据:CSV中存储纬度、经度字段,示例点为纬度28.56282,经度77.36824
可视化确认点在面范围内,但执行空间关联后无返回结果:
核心原因
问题出在坐标顺序不匹配:
Shapely库中所有几何对象的坐标参数顺序统一为(x, y),对应WGS84(EPSG:4326)坐标系下就是(经度, 纬度)。而你的数据存在两处顺序错误:
- 构造Point对象时,传参顺序写为
(纬度, 经度),和要求的顺序相反 - 面数据WKT中,坐标对存储顺序为
(纬度, 经度),加载后坐标同样错位
两份空间数据的坐标位置完全错位,自然无法匹配到结果。
修复代码
按如下逻辑修改即可正常匹配:
import pandas as pd import shapely.geometry from shapely.geometry import Point import geopandas as gpd from shapely import wkt from shapely.ops import transform # 处理点数据:调换经纬度顺序,符合Shapely要求的(经度, 纬度)格式 site_df = pd.read_csv(r'lat_long_file.csv') site_df['geometry'] = site_df.apply(lambda x: Point(x.LONG, x.LAT), axis='columns') gdf = gpd.GeoDataFrame(site_df, geometry = site_df.geometry, crs='EPSG:4326') # 处理面数据:加载WKT后翻转坐标顺序 polygon_df = pd.read_csv(r'polygon_csv_file.csv') def reverse_poly_coords(wkt_str): poly = wkt.loads(wkt_str) # 将(纬度, 经度)的坐标顺序翻转为(经度, 纬度) return transform(lambda x, y: (y, x), poly) polygon_df['geometry'] = polygon_df['polygon'].apply(reverse_poly_coords) gd_polygon = gpd.GeoDataFrame(polygon_df, geometry = polygon_df.geometry, crs='EPSG:4326') # 空间关联,新版本Geopandas用predicate参数替代已弃用的op参数 join_data = gpd.sjoin(gdf, gd_polygon, how="inner", predicate="within")
验证方法
修改后可以先执行单条数据验证逻辑是否正确:
test_point = Point(77.36824, 28.56282) test_poly = reverse_poly_coords("你的POLYGON字符串") # 返回True说明坐标顺序调整正确 print(test_poly.contains(test_point))
内容的提问来源于stack exchange,提问作者Smith

