문제 설명
LineString 유형의 개체는 JSON 직렬화가 불가능합니다. (Object of type LineString is not JSON serializable)
folium.GeoJSON을 사용할 때 이 오류를 어떻게 알 수 있습니까? gdf는 지리 데이터 프레임입니다. gdf.to_json()도 시도했지만 작동하지 않습니다. 저는 postgresql 데이터베이스(postgis)로 장고 환경에서 일하고 있습니다. geodataframe gdf는 geojson 파일에서 변환되었습니다. 이제 "'NoneType' 개체가 첨자할 수 없습니다.'라는 오류가 발생했습니다.
def retrieve_data_from_postgres(network_id,
set_initial_crs=4326,
zone_radius=15,
intersection_radius_percentage=0.8,
distance_offset_percentage=0.8,
line_color='orange',
link_side='right',
):
initial_crs = "EPSG:{}".format(set_initial_crs)
initial_crs = CRS(initial_crs)
CRS84 = "EPSG:4326"
default_crs = "EPSG:3857"
edges = Edge.objects.filter(network_id=network_id)
edges = serialize('geojson', edges,
fields=('id', 'param1', 'param2', 'param3', 'speed', 'length',
'lanes','geometry', 'name', 'source', 'target','network', 'road_type'))
edges = json.loads(edges)
edges_gdf = gpd.GeoDataFrame.from_features(edges['features']) # Convert a geojson as geodataframe
nodes = Node.objects.filter(network_id=network_id).values()
nodes_df = pd.DataFrame(nodes)
nodes_df['location'] = nodes_df['location'].apply(geometry.Point)
nodes_gdf = gpd.GeoDataFrame(nodes_df, geometry=nodes_df['location'])
edges_gdf.set_crs(initial_crs, inplace=True)
nodes_gdf.set_crs(initial_crs, inplace=True)
nodes_gdf.to_crs(CRS84, inplace=True)
zone_radius = zone_radius
intersection_radius = intersection_radius_percentage * zone_radius
distance_offset = distance_offset_percentage * zone_radius
tiles_layer = 'OpenStreetMap'
G = nx.from_pandas_edgelist(edges_gdf, 'source', 'target',
['speed', 'length', 'lanes', 'name', 'geometry'],
create_using=nx.MultiDiGraph())
# Add oneway column (it is a boolean column)
for u, v, d in G.edges(keys=False, data=True):
if G.has_edge(v, u):
G.edges[u, v, 0]['oneway'] = False
else:
G.edges[u, v, 0]['oneway'] = True
df_graph_to_pandas = nx.to_pandas_edgelist(G, source='source', target='target')
gdf = gpd.GeoDataFrame(df_graph_to_pandas, geometry='geometry')
gdf.set_crs(CRS84, inplace=True)
# On convertit en metre (m) avant d'appliquer le décalage afin
# d'uniformiser car parallel_offset se calcule en (m)
gdf.to_crs(crs=default_crs, inplace=True)
# Define parallel offset Geoserie
# geometry to offset and column it depends on
col_list = ['geometry', 'oneway']
gdf['_offset_geometry_'] = gdf[col_list].apply(
lambda x: x['geometry'].parallel_offset(
distance_offset, link_side) if not x['oneway']
else x['geometry'].parallel_offset(0, link_side),
axis=1)
# Drop old geometry and replace it by _offset_geometry_
gdf.drop('geometry', axis=1, inplace=True)
gdf.set_geometry('_offset_geometry_', inplace=True)
gdf.set_crs(default_crs, inplace=True)
# Converting back in 4326 before ploting
gdf.to_crs(crs=CRS84, inplace=True)
latitudes = list(nodes_gdf['geometry'].y)
longitudes = list(nodes_gdf['geometry'].x)
# Initialize the map
m = folium.Map(location=[latitudes[0], longitudes[0]],
max_zoom=18, prefer_canvas=True, tiles=tiles_layer)
print(gdf.columns)
layer=folium.GeoJson(
gdf,
tooltip=folium.GeoJsonTooltip(fields=['oneway','lanes',
'length','speed','name'],localize=True),
style_function=lambda x: {
'color': line_color
}).add_to(m)
# Bounding box the map such that the network is entirely center and visible
m.fit_bounds(layer.get_bounds())
# Adding the nodes points
for lat, long in list(zip(latitudes, longitudes)):
folium.Circle(location=[lat, long], color='cyan', fill=True,
fill_opacity=1,radius=intersection_radius).add_to(m)
m.save('templates/visualization.html')
참조 솔루션
방법 1:
Your GeoDataFrame gdf
contains a LineString geometry in another column apart from the active geometry. GeoPandas is currently (as of 0.9.0) not able to convert those to JSON (see this bug report https://github.com/geopandas/geopandas/issues/1906). You need to drop the affected column before passing it to folium
or convert it to something else yourself.
(by aba2s、martinfleis)