GeoJSON转GeoPandas DataFrame后参数丢失问题及解决方法
问题:GeoDataFrame转换与GeoJSON导出时保留
parameters字段的解决方法 问题场景
现有如下DataFrame:
d = { 'geoid': ['13085970205'], 'FIPS': ['13085'], 'Year': [2024], 'parameters': [{"Year": 2024, "hpi_prediction": 304.32205}], 'geometry':[ { "coordinates": [[[[-84.126456, 34.389734], [-84.12641, 34.39026], [-84.126323, 34.39068]]]], "parameters": {"Year": 2024, "hpi_prediction": 304.32205}, "type": "MultiPolygon" } ] } dd = pd.DataFrame(data=d)
执行以下GeoDataFrame转换代码时:
import geopandas as gpd df_geopandas_hpi = gpd.GeoDataFrame(dd[['geoid', 'geometry']])
原DataFrame中的parameters字段丢失。且实际业务中需要按如下代码批量导出GeoJSON并保留parameters字段:
if ~os.path.exists('../verus_data'): os.mkdir('../verus_data') for county, df_county in dd.groupby('FIPS'): if ~os.path.exists('../verus_data/'+str(county)): os.mkdir('../verus_data/'+str(county)) if ~os.path.exists('../verus_data/'+str(county)+'/'+'predicted'): os.mkdir('../verus_data/'+str(county)+'/'+'predicted') if ~os.path.exists('../verus_data/'+str(county)+'/'+'analyzed'): os.mkdir('../verus_data/'+str(county)+'/'+'analyzed') df_hpi = df_county[df_county['key'] == 'hpi'] df_analyzed = df_county[df_county['key'] == 'analyzed'] for year, df_year in df_hpi.groupby('Year'): if ~os.path.exists('../verus_data/'+str(county)+'/'+'predicted'+'/'+str(year)): os.mkdir('../verus_data/'+str(county)+'/'+'predicted'+'/'+str(year)) df_geopandas_hpi = gpd.GeoDataFrame(df_year[['geoid', 'geometry', 'parameters']]) df_geopandas_hpi.to_file('../verus_data/'+str(county)+'/'+'predicted'+'/'+str(year)+'/'+'hpi_predictions.geojson', driver="GeoJSON") for year, df_year in df_analyzed.groupby('Year'): if ~os.path.exists('../verus_data/'+str(county)+'/'+'analyzed'+'/'+str(year)): os.mkdir('../verus_data/'+str(county)+'/'+'analyzed'+'/'+str(year)) df_geopandas_analyzed = gpd.GeoDataFrame(df_year[['geoid', 'geometry', 'parameters']]) df_geopandas_analyzed.to_file('../verus_data/'+str(county)+'/'+'analyzed'+'/'+str(year)+'/'+'analyzed_values.geojson', driver="GeoJSON")
原因分析
- 直接列选取遗漏:最初的转换代码仅选取了
geoid和geometry两列,未包含parameters,因此该字段直接丢失。 - 几何对象转换特性:你的
geometry字段是geojson.geometry.MultiPolygon类型,Geopandas在将其转换为内部几何对象时,只会提取形状坐标信息,不会保留嵌套在几何对象内的parameters属性。 - 字典字段导出限制:即使在GeoDataFrame中保留了字典类型的
parameters列,若未正确设置CRS或转换几何类型,导出GeoJSON时可能出现字段序列化异常。
解决方法
1. 保留顶层parameters列并正确导出GeoJSON
修改代码,确保转换几何类型、保留目标字段并设置坐标系:
import geopandas as gpd import os import pandas as pd # 转换GeoJSON对象为Geopandas可识别的几何类型 def parse_geometry(geo_obj): return gpd.GeoSeries.from_features([geo_obj])[0] # 创建根目录 if not os.path.exists('../verus_data'): os.mkdir('../verus_data') # 按FIPS分组处理 for county, df_county in dd.groupby('FIPS'): county_dir = f'../verus_data/{county}' # 创建 county 目录 if not os.path.exists(county_dir): os.mkdir(county_dir) # 创建子目录 for sub_dir in ['predicted', 'analyzed']: sub_path = f'{county_dir}/{sub_dir}' if not os.path.exists(sub_path): os.mkdir(sub_path) # 筛选hpi和analyzed数据 df_hpi = df_county[df_county['key'] == 'hpi'] df_analyzed = df_county[df_county['key'] == 'analyzed'] # 处理hpi预测数据导出 for year, df_year in df_hpi.groupby('Year'): year_dir = f'{county_dir}/predicted/{year}' if not os.path.exists(year_dir): os.mkdir(year_dir) # 转换geometry列 df_year['geometry'] = df_year['geometry'].apply(parse_geometry) # 创建GeoDataFrame,保留所需字段并设置坐标系(WGS84) gdf = gpd.GeoDataFrame(df_year[['geoid', 'geometry', 'parameters']], crs="EPSG:4326") # 导出GeoJSON gdf.to_file(f'{year_dir}/hpi_predictions.geojson', driver="GeoJSON") # 处理analyzed数据导出 for year, df_year in df_analyzed.groupby('Year'): year_dir = f'{county_dir}/analyzed/{year}' if not os.path.exists(year_dir): os.mkdir(year_dir) df_year['geometry'] = df_year['geometry'].apply(parse_geometry) gdf = gpd.GeoDataFrame(df_year[['geoid', 'geometry', 'parameters']], crs="EPSG:4326") gdf.to_file(f'{year_dir}/analyzed_values.geojson', driver="GeoJSON")
2. 提取几何对象内部的parameters(可选)
如果需要把几何对象中嵌套的parameters也保留下来,可以添加提取逻辑:
# 提取geometry内部的parameters作为单独列 df_year['geo_parameters'] = df_year['geometry'].apply(lambda x: x.get('parameters', {})) # 合并顶层与几何内部的parameters(可选) df_year['combined_parameters'] = df_year.apply(lambda row: {**row['parameters'], **row['geo_parameters']}, axis=1) # 导出时使用合并后的字段 gdf = gpd.GeoDataFrame(df_year[['geoid', 'geometry', 'combined_parameters']], crs="EPSG:4326")
内容的提问来源于stack exchange,提问作者Wolfy
相关产品推荐
相关产品推荐

