Geopandas 将 geo_interface 中的几何图形读取为 Dataframe 中的 JSON 列
Geopandas read geometry from geo_interface as JSON column in Dataframe
我有一个 GeoDataFrame
,其中包含一个(多边形的)几何列和一些其他列,用于在地图上绘制多边形及其标记弹出窗口。我通过使用 gdf.__geo_interface__
作为列 geo
和其他属性将此数据框导出到使用 to_csv
的 CSV 文件中 DataFrame
.
geo
列看起来像
{'type': 'FeatureCollection', 'features': [{'id': '1', 'type': 'Feature', 'properties': {...}}
如何从 CSV 文件中读回并使用 CSV 获取 GeoDataFrame
?具体来说,我怎样才能重新创建我在 GeoDataFrame
?
中的原始列(多边形和属性)
鉴于以下情况:
from shapely.geometry import Point
d = {'col1': ['name1', 'name2'], 'geometry': [Point(1, 2), Point(2, 1)]}
gdf = geopandas.GeoDataFrame(d, crs="EPSG:4326")
gdf
您可以通过以下方式定义一个函数来展平任何 json
:
def flatten_nested_json_df(df):
df = df.reset_index()
s = (df.applymap(type) == list).all()
list_columns = s[s].index.tolist()
s = (df.applymap(type) == dict).all()
dict_columns = s[s].index.tolist()
while len(list_columns) > 0 or len(dict_columns) > 0:
new_columns = []
for col in dict_columns:
horiz_exploded = pd.json_normalize(df[col]).add_prefix(f'{col}.')
horiz_exploded.index = df.index
df = pd.concat([df, horiz_exploded], axis=1).drop(columns=[col])
new_columns.extend(horiz_exploded.columns) # inplace
for col in list_columns:
#print(f"exploding: {col}")
df = df.drop(columns=[col]).join(df[col].explode().to_frame())
new_columns.append(col)
s = (df[new_columns].applymap(type) == list).all()
list_columns = s[s].index.tolist()
s = (df[new_columns].applymap(type) == dict).all()
dict_columns = s[s].index.tolist()
return df
现在,您使用了 geo = gdf.__geo_interface__
,它返回了如下内容:
{'type': 'FeatureCollection',
'features': [{'id': '0',
'type': 'Feature',
'properties': {'col1': 'name1'},
'geometry': {'type': 'Point', 'coordinates': (1.0, 2.0)},
'bbox': (1.0, 2.0, 1.0, 2.0)},
{'id': '1',
'type': 'Feature',
'properties': {'col1': 'name2'},
'geometry': {'type': 'Point', 'coordinates': (2.0, 1.0)},
'bbox': (2.0, 1.0, 2.0, 1.0)}],
'bbox': (1.0, 1.0, 2.0, 2.0)}
请注意,我将其命名为 geo
。然后,这样做:
json = json.dumps(geo)
df = pd.json_normalize(geo)
flatten_nested_json_df(df)
哪个会给你:
index type bbox features.id features.type \
0 0 FeatureCollection (1.0, 1.0, 2.0, 2.0) 0 Feature
0 0 FeatureCollection (1.0, 1.0, 2.0, 2.0) 1 Feature
features.bbox features.properties.col1 features.geometry.type \
0 (1.0, 2.0, 1.0, 2.0) name1 Point
0 (2.0, 1.0, 2.0, 1.0) name2 Point
features.geometry.coordinates
0 (1.0, 2.0)
0 (2.0, 1.0)
我有一个 GeoDataFrame
,其中包含一个(多边形的)几何列和一些其他列,用于在地图上绘制多边形及其标记弹出窗口。我通过使用 gdf.__geo_interface__
作为列 geo
和其他属性将此数据框导出到使用 to_csv
的 CSV 文件中 DataFrame
.
geo
列看起来像
{'type': 'FeatureCollection', 'features': [{'id': '1', 'type': 'Feature', 'properties': {...}}
如何从 CSV 文件中读回并使用 CSV 获取 GeoDataFrame
?具体来说,我怎样才能重新创建我在 GeoDataFrame
?
鉴于以下情况:
from shapely.geometry import Point
d = {'col1': ['name1', 'name2'], 'geometry': [Point(1, 2), Point(2, 1)]}
gdf = geopandas.GeoDataFrame(d, crs="EPSG:4326")
gdf
您可以通过以下方式定义一个函数来展平任何 json
:
def flatten_nested_json_df(df):
df = df.reset_index()
s = (df.applymap(type) == list).all()
list_columns = s[s].index.tolist()
s = (df.applymap(type) == dict).all()
dict_columns = s[s].index.tolist()
while len(list_columns) > 0 or len(dict_columns) > 0:
new_columns = []
for col in dict_columns:
horiz_exploded = pd.json_normalize(df[col]).add_prefix(f'{col}.')
horiz_exploded.index = df.index
df = pd.concat([df, horiz_exploded], axis=1).drop(columns=[col])
new_columns.extend(horiz_exploded.columns) # inplace
for col in list_columns:
#print(f"exploding: {col}")
df = df.drop(columns=[col]).join(df[col].explode().to_frame())
new_columns.append(col)
s = (df[new_columns].applymap(type) == list).all()
list_columns = s[s].index.tolist()
s = (df[new_columns].applymap(type) == dict).all()
dict_columns = s[s].index.tolist()
return df
现在,您使用了 geo = gdf.__geo_interface__
,它返回了如下内容:
{'type': 'FeatureCollection',
'features': [{'id': '0',
'type': 'Feature',
'properties': {'col1': 'name1'},
'geometry': {'type': 'Point', 'coordinates': (1.0, 2.0)},
'bbox': (1.0, 2.0, 1.0, 2.0)},
{'id': '1',
'type': 'Feature',
'properties': {'col1': 'name2'},
'geometry': {'type': 'Point', 'coordinates': (2.0, 1.0)},
'bbox': (2.0, 1.0, 2.0, 1.0)}],
'bbox': (1.0, 1.0, 2.0, 2.0)}
请注意,我将其命名为 geo
。然后,这样做:
json = json.dumps(geo)
df = pd.json_normalize(geo)
flatten_nested_json_df(df)
哪个会给你:
index type bbox features.id features.type \
0 0 FeatureCollection (1.0, 1.0, 2.0, 2.0) 0 Feature
0 0 FeatureCollection (1.0, 1.0, 2.0, 2.0) 1 Feature
features.bbox features.properties.col1 features.geometry.type \
0 (1.0, 2.0, 1.0, 2.0) name1 Point
0 (2.0, 1.0, 2.0, 1.0) name2 Point
features.geometry.coordinates
0 (1.0, 2.0)
0 (2.0, 1.0)