У меня есть кадр геоданных с краями, возвращаемыми из OSMNX:
import osmnx as ox
# Getting graph for specific road
cf = '["highway"!~"motorway"]["ref"~"TF-563"]'
G = ox.graph_from_place('Tenerife, Spain', network_type='walk', simplify=False, custom_filter=cf)
# Adding length weights
G = ox.distance.add_edge_lengths(G)
# Getting nodes and edges of graph
nodes, edges = ox.convert.graph_to_gdfs(G, nodes=True)
Это дает столбец геометрии, где каждая строка содержит Linestring. Я хочу, чтобы у меня была одна длинная строка, упорядоченная правильно, чтобы я мог построить график, похожий на «edges.plot()», где все строки строятся непрерывно.
Для создания многострочной строки я использую следующее:
multi_line = geometry.MultiLineString(list(edges['geometry']))
Но когда я рисую это, все выглядит беспорядочно, и я предполагаю, что это связано с тем, что порядок строк в edges
фрейме геоданных не упорядочен, и поэтому строки соединяются случайным образом.
m = folium.Map(location=[28.105040, -16.610664], zoom_start=15)
# Extract coordinates from MultiLineString
def get_coordinates(multi_line):
all_coords = []
for line in multi_line.geoms:
all_coords.extend(list(line.coords))
return all_coords
# Get the coordinates
coordinates = get_coordinates(multi_line)
# Add the coordinates as PolyLines
folium.PolyLine([(coord[1], coord[0]) for coord in coordinates], color = "blue").add_to(m)
m
Кто-нибудь знает, есть ли способ упорядочить геометрию ребер, возвращаемую OSMNX, или есть другая причина, по которой я вижу эту проблему?
@Timeless Вопрос обновлен.
Спасибо за поправки. Вы не показываете, как вы «строите сюжет». Я не могу размножаться с помощью фолиума (см. здесь)
@Timeless снова обновлен с кодом для построения графика.
Если вам действительно не нужна одна единственная PolyLine , одним из вариантов может быть переиндексация краев:
extremities = [n for n, d in G.in_degree() if d == 1] # must be exactly 2 !
route = [(u,v) for u,v,*_ in list(nx.all_simple_edge_paths(G, *extremities))[0]]
# this requires geopandas>=1.0.0
single_ls = (
edges.droplevel(2).reindex(route)
.dissolve().geometry.line_merge().squeeze()
)
# otherwise, use from shapely.ops import linemerge
# single_ls = (
# linemerge(
# edges.droplevel(2).reindex(route)
# .dissolve().geometry.squeeze()
# )
# )
m = folium.Map(location=[28.105040, -16.610664], zoom_start=15)
folium.PolyLine(
[(coord[1], coord[0]) for coord in single_ls.coords],
color = "blue",
).add_to(m)
В противном случае вы можете просто исследовать оба узла/ребра:
m = edges.explore(
style_kwds=dict(weight=5, color = "black"),
location=[28.11114, -16.61616],
zoom_start=16,
)
m = nodes.explore(
m=m,
marker_type = "circle_marker",
marker_kwds=dict(radius=5),
style_kwds=dict(fillColor = "cyan", color = "black"),
)
Вывод (m
):
Это здорово, именно то, чего я пытался достичь! Спасибо!
Можете ли вы также предложить, как этот код можно повторно использовать, например, при работе с более крупными дорожными сетями; cf = '["шоссе"~"автомагистраль"]', поскольку это делает конечности > 2.
@Эллио Что мне делать, когда кто-то отвечает на мой вопрос?
Для этого вопроса было бы полезно использовать MRE, (
NameError: name 'G' is not defined
).