如何在GeoPandas DataFrame中由下游河段推导上游河段信息
基于GeoDataFrame推导水系上下游关联的实现方法
核心思路
利用已有的下游关联数据反向构建上游映射字典,再将关联关系合并回GeoDataFrame,最后按海拔降序完成排序。
实现步骤与代码示例
假设你的GeoDataFrame(命名为gdf)包含以下核心字段:
reach_id: 河段唯一标识(整数/字符串)downstream_id: 该河段的下游河段ID(无下游则为None/NaN)elevation: 河段海拔值(用于排序)- 地理字段(如
geometry,存储多边形几何信息)
1. 构建上游关联映射字典
遍历所有下游关联记录,将每个下游河段对应的上游河段收集到列表中:
import pandas as pd import geopandas as gpd # 初始化上游映射字典,默认值为空列表 upstream_map = {} for idx, row in gdf.iterrows(): reach = row['reach_id'] downstream = row['downstream_id'] # 跳过无下游的河段(如河口) if pd.notna(downstream): # 若下游未在字典中,先创建空列表 if downstream not in upstream_map: upstream_map[downstream] = [] upstream_map[downstream].append(reach)
2. 将上游关联合并到GeoDataFrame
新增upstream_ids列,存储当前河段的所有上游ID:
# 匹配每个河段的上游列表,无上游则返回空列表 gdf['upstream_ids'] = gdf['reach_id'].apply(lambda x: upstream_map.get(x, []))
3. 按海拔从高到低排序
直接对GeoDataFrame按elevation字段降序排列:
# 降序排序后重置索引 gdf_sorted = gdf.sort_values(by='elevation', ascending=False).reset_index(drop=True)
边界情况处理
- 源头河段:无上游的河段,
upstream_ids会自动返回空列表,符合逻辑。 - 河口河段:无下游的河段,
downstream_id为NaN,不会被加入上游映射字典,不影响其他河段的关联推导。 - 1对多场景:比如河段5的上游是2和4,
upstream_map[5]会自动收集到[2,4],最终对应河段的upstream_ids字段就是该列表。
完整测试示例
import pandas as pd import geopandas as gpd # 模拟测试数据(替换为你的实际GeoDataFrame) data = { 'reach_id': [1,2,3,4,5,6], 'downstream_id': [2,5,5,5,6, None], 'elevation': [1000, 800, 750, 780, 600, 500], 'geometry': [None]*6 # 实际为多边形几何对象 } gdf = gpd.GeoDataFrame(data, crs="EPSG:4326") # 构建上游映射 upstream_map = {} for idx, row in gdf.iterrows(): reach = row['reach_id'] downstream = row['downstream_id'] if pd.notna(downstream): if downstream not in upstream_map: upstream_map[downstream] = [] upstream_map[downstream].append(reach) # 添加上游关联列 gdf['upstream_ids'] = gdf['reach_id'].apply(lambda x: upstream_map.get(x, [])) # 按海拔降序排序 gdf_sorted = gdf.sort_values(by='elevation', ascending=False).reset_index(drop=True) # 输出结果查看 print(gdf_sorted[['reach_id', 'downstream_id', 'upstream_ids', 'elevation']])
运行后会得到按海拔从高到低排列的河段数据,每个河段的上下游关联关系清晰可查。
内容的提问来源于stack exchange,提问作者user23273464
相关产品推荐
相关产品推荐

