如何用Python从Pandas DataFrame生成地理边界层级JSON树形结构?
解决方案:构建州→县→城市的层级地理JSON树形结构
树形结构 vs 邻接表:哪种更适合?
对于你的固定三级层级(州→县→城市)需求,树形结构更合适:
- 树形结构直观体现父子层级关系,前端渲染树形组件、搜索匹配节点都非常直接,无需额外关联查询;
- 邻接表(每个节点存储父ID)更适合层级不固定、需要动态扩展或存储在数据库中做复杂查询的场景,你的需求用树形结构效率更高、实现更简单。
具体实现步骤(Python)
1. 依赖库准备
确保安装所需库:
pip install pandas shapely
2. 数据预处理:转换Geometry为GeoJSON格式
Shapely的Polygon对象无法直接序列化为JSON,需要先转成GeoJSON格式的字典:
import pandas as pd import json from shapely.geometry import mapping
3. 构建层级节点并关联
步骤1:构建州节点字典
# 处理州数据(Df3),生成州节点字典 state_dict = {} for _, row in Df3.iterrows(): state_id = row["State ID"] state_dict[state_id] = { "id": state_id, "name": row["State"], "geometry": mapping(row["geometry"]), # 转GeoJSON格式 "children": [] }
步骤2:构建县节点并关联到州
# 处理县数据(Df2),生成县节点字典并关联到对应州 county_dict = {} for _, row in Df2.iterrows(): county_id = row["County ID"] state_id = row["State ID"] county_node = { "id": county_id, "name": row["County"], "geometry": mapping(row["geometry"]), "children": [] } county_dict[county_id] = county_node # 将县节点添加到对应州的子节点列表 if state_id in state_dict: state_dict[state_id]["children"].append(county_node)
步骤3:构建城市节点并关联到县
# 处理城市数据(Df1),生成城市节点并关联到对应县 for _, row in Df1.iterrows(): city_id = row["City ID"] county_id = row["County ID"] city_node = { "id": city_id, "name": row["City"], "geometry": mapping(row["geometry"]), "children": [] # 城市无子节点,留空 } # 将城市节点添加到对应县的子节点列表 if county_id in county_dict: county_dict[county_id]["children"].append(city_node)
4. 生成最终树形JSON
# 将州字典转为列表(树的根节点集合) tree_data = list(state_dict.values()) # 序列化为JSON字符串 tree_json = json.dumps(tree_data, indent=2) # 保存到文件(可选) with open("geo_hierarchy.json", "w", encoding="utf-8") as f: f.write(tree_json)
搜索任一层级节点的实现
可以通过递归遍历树形结构,匹配节点的ID或名称,快速获取对应的Polygon:
def search_geo_node(tree, keyword, search_by="name"): """ 递归搜索树形结构中的节点 :param tree: 树形数据列表 :param keyword: 搜索关键词 :param search_by: 搜索字段("id"或"name") :return: 匹配的节点列表 """ matches = [] for node in tree: if str(node[search_by]) == str(keyword): matches.append(node) # 递归搜索子节点 if node["children"]: matches.extend(search_geo_node(node["children"], keyword, search_by)) return matches # 示例:搜索名称为"Los Angeles"的城市 matches = search_geo_node(tree_data, "Los Angeles") if matches: print("匹配到的Polygon:", matches[0]["geometry"])
内容的提问来源于stack exchange,提问作者Salem Moussa
相关产品推荐
相关产品推荐

