💻 Nettverksanalyse i Python#
Å finne en korteste vei ved hjelp av et bestemt gate-nettverk er et vanlig GIS-problem som har mange praktiske applikasjoner. For eksempel, navigasjon, en av de ‘hverdagslige’ applikasjonene der rute-algoritmer brukes til å finne den optimale ruten mellom to eller flere punkter.
Selvfølgelig har Python-økosystemet produsert pakker som kan brukes til å gjennomføre nettverksanalyser, som for eksempel ruting. NetworkX-pakken gir forskjellige verktøy for å analysere nettverk, og implementerer flere forskjellige rutealgoritmer, som for eksempel Dijkstra’s eller A*-algoritmene. Begge er vanligvis brukt til å finne korteste veier langs transportnettverk.
For å kunne utføre nettverksanalyse, er det selvfølgelig nødvendig å ha et nettverk som brukes til analysene. OSMnx-pakken lar oss hente rutbare nettverk fra OpenStreetMap for forskjellige transportformer (gange, sykling og kjøring). OSMnx-pakken pakker også noen av NetworkX-funksjonene på en praktisk måte for bruk på OpenStreetMap-data.
I følgende avsnitt vil vi bruke OSMnx til å finne den korteste veien mellom to punkter basert på sykkelbare veier. Med bare de minste modifikasjonene, kan vi deretter gjenta analysen for det gangbare gatenettverket.
Få et rutbart nettverk#
For å laste ned OpenStreetMap-data som representerer gatenettverket, kan vi bruke
dens
graph_from_place()
-funksjon. Som parametere forventer den et stedsnavn og, valgfritt, en nettverkstype.
import osmnx
PLACE_NAME = "Grunerløkka, Oslo, Norway"
graph = osmnx.graph_from_place(
PLACE_NAME,
network_type="bike"
)
figure, ax = osmnx.plot_graph(graph)

Proft tips!
Noen ganger kan den korteste veien gå litt utenfor det definerte interesseområdet. For å ta hensyn til dette, kan vi hente nettverket for et litt større område enn Grünerløkka bydel, i tilfelle den korteste veien ikke er helt innenfor bydelsgrensene.
# Få området av interesse polygon
place_polygon = osmnx.geocode_to_gdf(PLACE_NAME)
# Re-projiser polygonet til en lokal projisert CRS (slik at CRS-enheten er meter)
place_polygon = place_polygon.to_crs("EPSG:25833")
# Buffer med 200 meter
place_polygon["geometry"] = place_polygon.buffer(200)
# Re-projiser polygonet tilbake til WGS84 (kreves av OSMnx)
place_polygon = place_polygon.to_crs("EPSG:4326")
# Hent nettverksgraf
graph = osmnx.graph_from_polygon(
place_polygon.at[0, "geometry"],
network_type="bike"
)
fig, ax = osmnx.plot_graph(graph)

Dataoversikt#
Nå som vi har fått et komplett nettverksdiagram for den reisemåten vi spesifiserte (sykling), kan vi ta en nærmere titt på hvilke attributter som er tildelt noder og kanter i nettverket. Det er sannsynligvis lettest å først konvertere nettverket til en geodata-frame der vi deretter kan bruke verktøyene vi lærte i tidligere leksjoner.
For å konvertere et diagram til en geodata-frame, kan vi bruke osmnx.graph_to_gdfs()
. Her kan vi gjøre bruk av funksjonens parametere nodes
og edges
for å velge om vi vil ha
bare noder, bare kanter, eller begge (standard):
# Hent bare kanter fra grafen
edges = osmnx.graph_to_gdfs(graph, nodes=False, edges=True)
edges.head()
osmid | oneway | name | highway | maxspeed | reversed | length | geometry | lanes | ref | width | tunnel | junction | bridge | service | access | |||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
u | v | key | ||||||||||||||||
79316 | 25335244 | 0 | 3236576 | True | Møllergata | unclassified | 30 | False | 108.269 | LINESTRING (10.75135 59.91923, 10.75131 59.919... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
6945985051 | 0 | 39825586 | False | Rosteds gate | residential | 30 | True | 81.266 | LINESTRING (10.75135 59.91923, 10.75113 59.919... | 2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
1424670590 | 0 | 311012187 | False | Hausmanns gate | secondary | 30 | True | 31.268 | LINESTRING (10.75135 59.91923, 10.75153 59.919... | 2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
8714388689 | 0 | 1044541319 | True | NaN | cycleway | NaN | False | 20.933 | LINESTRING (10.75135 59.91923, 10.75152 59.919... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
79317 | 25389708 | 0 | 4854886 | False | Wilses gate | living_street | 8 | True | 73.470 | LINESTRING (10.75036 59.91792, 10.75029 59.917... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
Den resulterende geodata-framen består av en lang liste med kolonner. De fleste av dem
relaterer til OpenStreetMap-tags, og
navnene deres er ganske selvforklarende. Kolonnene u
og v
beskriver
topologisk forhold innen nettverket: de betegner start- og slutt-noden
for hver kant.
Kolonne |
Beskrivelse |
Datatype |
---|---|---|
Broelement |
boolean |
|
geometry |
Geometri av elementet |
Shapely.geometry |
Tag for veier (veitype) |
str / list |
|
Antall kjørefelt |
int (or nan) |
|
Lengden på elementet (meter) |
float |
|
Maksimal lovlige hastighetsbegrensning |
int /list |
|
Navn på (gata) elementet |
str (or nan) |
|
Enveisvei |
boolean |
|
Unike id-er for elementet |
list |
|
Startnoden for kanten |
int |
|
Sluttnoden for kanten |
int |
Hvilke typer gater består nettverket vårt av?
edges["highway"].value_counts()
highway
service 1683
residential 1343
cycleway 745
secondary 352
path 300
tertiary 283
unclassified 221
primary 166
living_street 65
pedestrian 47
trunk 30
[path, service] 30
[cycleway, residential] 26
trunk_link 21
[service, residential] 20
[unclassified, service] 4
[cycleway, service] 4
[path, residential] 4
[unclassified, residential] 3
[unclassified, cycleway] 2
[pedestrian, service] 2
[pedestrian, living_street, service] 2
[path, cycleway, service] 2
[cycleway, living_street] 2
[living_street, cycleway] 2
[pedestrian, service, residential] 2
[pedestrian, cycleway] 2
[trunk_link, trunk] 1
Name: count, dtype: int64
Transformere til projisert referansesystem#
Nettverksdataens kartografiske referansesystem (CRS) er WGS84 (EPSG:4326), et geografisk referansesystem. Det betyr at avstander er registrert og uttrykt i grader. Dette er ikke praktisk for nettverksanalyser, som for eksempel å finne en korteste vei.
Igjen, OSMnx’s graf-objekter tilbyr ikke en metode for å transformere deres
geodata, men OSMnx kommer med en separat funksjon:
osmnx.project_graph()
tar en inngangsgraf og en CRS som parametere, og returnerer en ny, transformert,
graf. Hvis crs
utelates, er transformasjonen standard til den mest
egnede UTM-sonen lokalt.
# Transformere grafen til UTM
graph = osmnx.project_graph(graph)
# Hent re-projiserte noder og kanter
nodes, edges = osmnx.graph_to_gdfs(graph)
nodes.crs
<Projected CRS: EPSG:32632>
Name: WGS 84 / UTM zone 32N
Axis Info [cartesian]:
- E[east]: Easting (metre)
- N[north]: Northing (metre)
Area of Use:
- name: Between 6°E and 12°E, northern hemisphere between equator and 84°N, onshore and offshore. Algeria. Austria. Cameroon. Denmark. Equatorial Guinea. France. Gabon. Germany. Italy. Libya. Liechtenstein. Monaco. Netherlands. Niger. Nigeria. Norway. Sao Tome and Principe. Svalbard. Sweden. Switzerland. Tunisia. Vatican City State.
- bounds: (6.0, 0.0, 12.0, 84.0)
Coordinate Operation:
- name: UTM zone 32N
- method: Transverse Mercator
Datum: World Geodetic System 1984 ensemble
- Ellipsoid: WGS 84
- Prime Meridian: Greenwich
Analysering av nettverksegenskaper#
Nå som vi har forberedt et rutbart nettverksdiagram, kan vi gå over til de mer
analytiske funksjonene til OSMnx, og hente informasjon om nettverket.
For å beregne grunnleggende nettverksegenskaper, bruk
osmnx.basic_stats()
:
# Beregn nettverksstatistikk
osmnx.basic_stats(graph)
{'n': 2407,
'm': 5364,
'k_avg': 4.457000415454923,
'edge_length_total': 303132.26999999996,
'edge_length_avg': 56.512354586129746,
'streets_per_node_avg': 2.5592023265475694,
'streets_per_node_counts': {0: 0, 1: 658, 2: 21, 3: 1459, 4: 262, 5: 7},
'streets_per_node_proportions': {0: 0.0,
1: 0.2733693394266722,
2: 0.008724553385957623,
3: 0.6061487328624844,
4: 0.10884918986289988,
5: 0.0029081844619858743},
'intersection_count': 1749,
'street_length_total': 169802.93599999987,
'street_segment_count': 3014,
'street_length_avg': 56.33806768414063,
'circuity_avg': 1.0651316280918361,
'self_loop_proportion': 0.0026542800265428003}
Dette gir oss ennå ikke alle interessante egenskaper ved nettverket vårt, som OSMnx ikke automatisk tar hensyn til området som er dekket av nettverket. Vi kan gjøre det manuelt, ved, først, å avgrense nettverkets convex hull (fra en ‘unary’ union av alle funksjonene), og deretter, andre, beregne området av dette skallet.
convex_hull = edges.unary_union.convex_hull
convex_hull
/tmp/ipykernel_2307/2186647520.py:1: DeprecationWarning: The 'unary_union' attribute is deprecated, use the 'union_all()' method instead.
convex_hull = edges.unary_union.convex_hull
stats = osmnx.basic_stats(graph, area=convex_hull.area)
stats
{'n': 2407,
'm': 5364,
'k_avg': 4.457000415454923,
'edge_length_total': 303132.26999999996,
'edge_length_avg': 56.512354586129746,
'streets_per_node_avg': 2.5592023265475694,
'streets_per_node_counts': {0: 0, 1: 658, 2: 21, 3: 1459, 4: 262, 5: 7},
'streets_per_node_proportions': {0: 0.0,
1: 0.2733693394266722,
2: 0.008724553385957623,
3: 0.6061487328624844,
4: 0.10884918986289988,
5: 0.0029081844619858743},
'intersection_count': 1749,
'street_length_total': 169802.93599999987,
'street_segment_count': 3014,
'street_length_avg': 56.33806768414063,
'circuity_avg': 1.0651316280918361,
'self_loop_proportion': 0.0026542800265428003,
'node_density_km': 321.86957012617927,
'intersection_density_km': 233.8802983592387,
'edge_density_km': 40535.543596291194,
'street_density_km': 22706.438727246816}
Som vi kan se, har vi nå mye informasjon om gatenettverket vårt som kan brukes til å forstå strukturen. Vi kan for eksempel se at gjennomsnittlig nodetetthet i nettverket vårt er 321.9 noder/km og at den totale kantlengden på nettverket vårt er mer enn 303 kilometer.
Korteste vei-analyse#
La oss nå beregne den korteste veien mellom to punkter ved hjelp av
osmnx.shortest_path()
.
Opprinnelses- og destinasjonspunkter#
Først må vi spesifisere opprinnelses- og destinasjonspunkter for ruten vår. Hvis du er kjent med Grünerløkka-området, kan du spesifisere et egendefinert stedsnavn som en kildeposisjon. Eller, du kan følge med og velge disse punktene som opprinnelse og destinasjon i analysen:
Trondheimsveien 110 C, Oslo, Norway
: Carl Berner-krysset.Grünerhagen
, en park nederst på Løkka.
Vi kunne finne ut koordinatene for disse stedene manuelt, og lage
shapely.geometry.Point
s basert på koordinatene. Men hvis vi ville ha
mer enn bare to punkter, ville det raskt bli et ork. I stedet kan vi
bruke OSMnx til å geokode lokasjonene.
Husk å transformere opprinnelses- og destinasjonspunktene til samme referanse system som nettverksdataene.
origin = (
osmnx.geocode_to_gdf("Trondheimsveien 110 C, Oslo, Norway", which_result=1) # hent geolokasjon
.to_crs(edges.crs) # transformer til UTM
.at[0, "geometry"] # velg geometri av første rad
)
destination = (
osmnx.geocode_to_gdf("Grünerhagen")
.to_crs(edges.crs)
.at[0, "geometry"]
.centroid
)
Vi har nå shapely.geometry.Point
s som representerer opprinnelses- og destinasjon
plasseringene for nettverksanalysen vår. I en neste trinn, må vi finne disse punktene på
det rutbare nettverket før den endelige rutingen.
Nærmeste node#
For å rute på nettverket, må vi først finne et startpunkt og sluttpunkt
som er en del av nettverket. Bruk
osmnx.distance.nearest_nodes()
for å returnere den nærmeste nodens ID:
origin_node_id = osmnx.nearest_nodes(graph, origin.x, origin.y)
origin_node_id
832779407
destination_node_id = osmnx.nearest_nodes(graph, destination.x, destination.y)
destination_node_id
16193897
Ruting#
Nå er vi klare for ruting og for å finne den korteste veien mellom
opprinnelses- og målplasseringene. Vi vil bruke
osmnx.shortest_path()
.
Funksjonen tar tre obligatoriske parametere: en graf, en opprinnelsesnod-id, og
en destinasjonsnod-id, og to valgfrie parametere: weight
kan settes til
å vurdere en annen kostnadsimpedans enn lengden på ruten, og cpus
kontrollerer parallell beregning av mange ruter.
# Finn den korteste veien mellom opprinnelse og destinasjon
route = osmnx.shortest_path(graph, origin_node_id, destination_node_id)
route
[832779407,
2481252143,
841832182,
12534265,
79607,
330463916,
79605,
106138,
5580791789,
10973871838,
4618464230,
12534258,
4618464227,
1387802061,
1426810245,
106168,
106141,
106169,
106171,
837970612,
10178369286,
16193897]
Som et resultat får vi en liste over alle nodene som er langs den korteste veien.
Vi kunne hente plasseringene til disse nodene fra nodes
GeoDataFramen og lage en LineString-presentasjon av punktene, men heldigvis,
OSMnx kan gjøre det for oss og vi kan plotte korteste vei ved hjelp av
plot_graph_route()
-funksjonen:
# Plot den korteste veien
fig, ax = osmnx.plot_graph_route(graph, route)

Flott! Nå har vi den korteste veien mellom opprinnelses- og målplasseringene våre. Å kunne analysere korteste veier mellom steder kan være verdifull informasjon for mange applikasjoner. Her analyserte vi bare de korteste veiene basert på avstand, men ganske ofte er det mer nyttig å finne de optimale rutene mellom steder basert på reisetiden. Her, for eksempel kunne vi beregne tiden det tar å krysse hvert veisegment ved å dele lengden på veisegmentet med fartsgrensen og beregne de optimale rutene ved å ta hensyn til fartsgrensene også som kan endre resultatet spesielt på lengre turer enn her.
Lagre korteste veier til disk#
Ganske ofte må du lagre ruten til en fil for videre analyse og visualiseringsformål, eller i det minste ha den som et GeoDataFrame-objekt i Python. La oss derfor fortsette litt til og se hvordan vi kan lage ruten til en linjestreng og lagre den korteste veigeometrien og relaterte attributter i en geopackage-fil.
Først må vi få nodene som tilhører den korteste veien:
# Få nodene langs den korteste veien
route_nodes = nodes.loc[route]
route_nodes
y | x | highway | street_count | lon | lat | ref | geometry | |
---|---|---|---|---|---|---|---|---|
osmid | ||||||||
832779407 | 6.644504e+06 | 599257.916763 | NaN | 3 | 10.775706 | 59.926021 | NaN | POINT (599257.917 6644503.528) |
2481252143 | 6.644431e+06 | 599258.760391 | NaN | 4 | 10.775686 | 59.925368 | NaN | POINT (599258.76 6644430.804) |
841832182 | 6.644408e+06 | 599241.069524 | NaN | 3 | 10.775359 | 59.925170 | NaN | POINT (599241.07 6644408.291) |
12534265 | 6.644354e+06 | 599198.726208 | NaN | 3 | 10.774576 | 59.924697 | NaN | POINT (599198.726 6644354.409) |
79607 | 6.644248e+06 | 599114.681136 | NaN | 3 | 10.773023 | 59.923766 | NaN | POINT (599114.681 6644248.447) |
330463916 | 6.644186e+06 | 599065.091608 | NaN | 3 | 10.772106 | 59.923213 | NaN | POINT (599065.092 6644185.549) |
79605 | 6.644070e+06 | 598990.718616 | traffic_signals | 4 | 10.770721 | 59.922193 | NaN | POINT (598990.719 6644069.855) |
106138 | 6.643971e+06 | 598936.431294 | NaN | 4 | 10.769704 | 59.921318 | NaN | POINT (598936.431 6643970.977) |
5580791789 | 6.643978e+06 | 598905.840513 | NaN | 3 | 10.769160 | 59.921385 | NaN | POINT (598905.841 6643977.636) |
10973871838 | 6.643998e+06 | 598808.771092 | NaN | 3 | 10.767434 | 59.921596 | NaN | POINT (598808.771 6643998.474) |
4618464230 | 6.644015e+06 | 598727.331337 | NaN | 3 | 10.765987 | 59.921766 | NaN | POINT (598727.331 6644015.331) |
12534258 | 6.644040e+06 | 598608.730564 | NaN | 3 | 10.763878 | 59.922015 | NaN | POINT (598608.731 6644039.89) |
4618464227 | 6.644047e+06 | 598574.797489 | NaN | 3 | 10.763275 | 59.922086 | NaN | POINT (598574.797 6644046.918) |
1387802061 | 6.644070e+06 | 598458.146066 | traffic_signals | 4 | 10.761200 | 59.922323 | NaN | POINT (598458.146 6644070.197) |
1426810245 | 6.643977e+06 | 598459.143340 | NaN | 3 | 10.761173 | 59.921483 | NaN | POINT (598459.143 6643976.587) |
106168 | 6.643929e+06 | 598460.276750 | traffic_signals | 3 | 10.761171 | 59.921059 | NaN | POINT (598460.277 6643929.364) |
106141 | 6.643929e+06 | 598355.529450 | NaN | 4 | 10.759298 | 59.921076 | NaN | POINT (598355.529 6643928.517) |
106169 | 6.643927e+06 | 598248.893522 | NaN | 4 | 10.757391 | 59.921090 | NaN | POINT (598248.894 6643927.178) |
106171 | 6.643926e+06 | 598156.956908 | NaN | 3 | 10.755747 | 59.921100 | NaN | POINT (598156.957 6643925.874) |
837970612 | 6.643926e+06 | 598115.499469 | NaN | 3 | 10.755006 | 59.921111 | NaN | POINT (598115.499 6643925.978) |
10178369286 | 6.643944e+06 | 598123.855354 | NaN | 4 | 10.755164 | 59.921270 | NaN | POINT (598123.855 6643943.949) |
16193897 | 6.643977e+06 | 598146.833170 | NaN | 3 | 10.755590 | 59.921562 | NaN | POINT (598146.833 6643977.092) |
Som vi kan se, har vi nå alle nodene som var en del av den korteste veien som en GeoDataFrame.
Nå kan vi lage en LineString ut av punktgeometriene til nodene:
import shapely.geometry
# Lag en geometri for den korteste veien
route_line = shapely.geometry.LineString(
list(route_nodes.geometry.values)
)
route_line
Nå har vi ruten som en LineString-geometri.
La oss lage en GeoDataFrame ut av den med litt nyttig informasjon om ruten vår, for eksempel en liste over osm-idene som er en del av ruten og lengden på ruten.
import geopandas
route_geom = geopandas.GeoDataFrame(
{
"geometry": [route_line],
"osm_nodes": [route],
},
crs=edges.crs
)
# Beregn rute-lengden
route_geom["length_m"] = route_geom.length
route_geom.head()
geometry | osm_nodes | length_m | |
---|---|---|---|
0 | LINESTRING (599257.917 6644503.528, 599258.76 ... | [832779407, 2481252143, 841832182, 12534265, 7... | 1669.84227 |
Nå har vi en GeoDataFrame som vi kan lagre til disk. La oss fortsatt bekrefte at alt er ok ved å plotte ruten vår på toppen av gatenettverket og noen bygninger, og plot også opprinnelses- og målpunktene på toppen av kartet vårt.
Last ned bygninger:
bygninger = osmnx.features_from_place(
PLACE_NAME,
{
"building" : True
}
).to_crs(edges.crs)
La oss nå plotte ruten og gatenettverkselementene for å bekrefte at alt er som det skal:
import contextily
import matplotlib.pyplot
fig, ax = matplotlib.pyplot.subplots(figsize=(12,8))
# Plot kanter og noder
edges.plot(ax=ax, linewidth=0.75, color='gray')
nodes.plot(ax=ax, markersize=2, color='gray')
# Legg til bygninger
ax = bygninger.plot(ax=ax, facecolor='lightgray', alpha=0.7)
# Legg til ruten
ax = route_geom.plot(ax=ax, linewidth=2, linestyle='--', color='red')
# Legg til bakgrunnskart
contextily.add_basemap(ax, crs=bygninger.crs, source=contextily.providers.CartoDB.Positron)

Flott, alt ser ut til å være i orden! Som du kan se, har vi nå full kontroll over alle elementene i kartet vårt, og vi kan bruke alle estetiske egenskaper som matplotlib gir for å endre hvordan kartet vårt vil se ut. Nå er vi nesten klare til å lagre dataene våre på disk.
Forbered data for lagring til fil#
Dataene inneholder visse datatyper (som list
) som bør konverteres
til tegnstrenger før du lagrer dataene til fil (et alternativ ville være
å droppe ugyldige kolonner).
edges.head()
osmid | oneway | name | highway | maxspeed | reversed | length | geometry | lanes | tunnel | junction | ref | width | bridge | service | access | |||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
u | v | key | ||||||||||||||||
79316 | 25335244 | 0 | 3236576 | True | Møllergata | unclassified | 30 | False | 108.269 | LINESTRING (597916.667 6643710.788, 597914.829... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
6945985051 | 0 | 39825586 | False | Rosteds gate | residential | 30 | True | 81.266 | LINESTRING (597916.667 6643710.788, 597904.519... | 2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
1424670590 | 0 | 311012187 | False | Hausmanns gate | secondary | 30 | True | 31.268 | LINESTRING (597916.667 6643710.788, 597926.961... | 2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
8714388689 | 0 | 1044541319 | True | NaN | cycleway | NaN | False | 20.933 | LINESTRING (597916.667 6643710.788, 597926.099... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
25335244 | 79317 | 0 | 3236576 | True | Møllergata | unclassified | 30 | False | 47.137 | LINESTRING (597882.414 6643608.012, 597877.956... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
# Kolonner med ugyldige verdier
problematiske_kolonner = [
"osmid",
"lanes",
"name",
"highway",
"width",
"maxspeed",
"reversed",
"junction",
"bridge",
"tunnel",
"access",
"service",
]
# konverter valgte kolonner til strengformat
edges[problematiske_kolonner] = edges[problematiske_kolonner].to_string()
route_geom["osm_nodes"] = route_geom["osm_nodes"].astype(str)
print(edges.dtypes)
osmid object
oneway bool
name object
highway object
maxspeed object
reversed object
length float64
geometry geometry
lanes object
tunnel object
junction object
ref object
width object
bridge object
service object
access object
dtype: object
Nå kan vi se at de fleste attributtene er av typen object
som ganske ofte (som vår her) refererer til en datatypetype.
Lagre dataene:#
import pathlib
NOTEBOOK_PATH = pathlib.Path().resolve()
DATA_MAPPE = NOTEBOOK_PATH / "data"
Avhengig av hvor stort interesseområde vi har definert, så kan denne filen bli veldig stor, derfor lagrer vi bare ruten i denne omgang:
# Lagre ett lag etter et annet
output_gpkg = DATA_MAPPE / "osm_data"/ "OSM_Grunerlokka.gpkg"
#edges = edges[["osmid","name","highway","maxspeed","length","geometry","width"]]
#edges.to_file(output_gpkg, layer="streets")
route_geom.to_file(output_gpkg, layer="route")
#nodes.to_file(output_gpkg, layer="nodes")
#bygninger[['geometry', 'name', 'addr:street']].to_file(output_gpkg, layer="buildings")
display(bygninger.describe())
display(bygninger)
amenity | capacity | fee | name | operator | parking | wheelchair | geometry | bicycle | foot | ... | ref | advertising | mapillary | name:signed | substation | man_made | craft | ways | type | location | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 33 | 5 | 6 | 80 | 13 | 1 | 15 | 3682 | 1 | 1 | ... | 1 | 1 | 1 | 1 | 1 | 4 | 1 | 16 | 16 | 3 |
unique | 15 | 4 | 2 | 78 | 7 | 1 | 3 | 3682 | 1 | 1 | ... | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 16 | 1 | 1 |
top | place_of_worship | 500 | yes | Chokoladefabrikken | Kirkelig fellesråd i Oslo | multi-storey | limited | POLYGON ((599664.3266955729 6645572.2019701665... | yes | yes | ... | 1735 | board | 293938462404822 | no | minor_distribution | silo | yes | [133363272, 112236630] | multipolygon | indoor |
freq | 10 | 2 | 3 | 2 | 5 | 1 | 6 | 1 | 1 | 1 | ... | 1 | 1 | 1 | 1 | 1 | 3 | 1 | 1 | 16 | 3 |
4 rows × 98 columns
amenity | capacity | fee | name | operator | parking | wheelchair | geometry | bicycle | foot | ... | ref | advertising | mapillary | name:signed | substation | man_made | craft | ways | type | location | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
element_type | osmid | |||||||||||||||||||||
way | 9334580 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POLYGON ((599664.327 6645572.202, 599700.091 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
27011865 | NaN | NaN | yes | Zoologisk museum | UiO | NaN | limited | POLYGON ((599021.107 6643847.082, 599007.188 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
27011866 | NaN | NaN | yes | Geologisk museum | UiO | NaN | limited | POLYGON ((599096.358 6643849.709, 599075.963 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
27011867 | NaN | NaN | NaN | Lids hus | UiO | NaN | limited | POLYGON ((599103.169 6643631.899, 599088.901 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
27011868 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POLYGON ((599012.323 6643681.946, 599011.947 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
relation | 13803840 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POLYGON ((597928.252 6644296.877, 597927.103 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [1031362635, 112898983] | multipolygon | NaN |
13803841 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POLYGON ((598151.179 6643166.871, 598163.554 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [112236619, 1031362641] | multipolygon | NaN | |
15885246 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POLYGON ((600151.857 6643897.11, 600142.549 66... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [486231544, 1174948320, 1174948319] | multipolygon | NaN | |
15896730 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POLYGON ((600162.955 6645115.376, 600163.099 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [1024970009, 1175254280] | multipolygon | NaN | |
15896731 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POLYGON ((600118.937 6645122.072, 600155.178 6... | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [1175254283, 64605831, 1175254281] | multipolygon | NaN |
3682 rows × 98 columns
Flott, nå har vi lagret alle dataene som ble brukt til å produsere kartene i en geopakke.
Videre lesing#
Her lærte vi hvordan man løser en enkel ruteoppgave mellom opprinnelses- og målpunkt. Hva om vi har hundrevis eller tusenvis av opprinnelser? Dette er tilfelle hvis du vil utforske reiseavstandene til en spesifikk plassering over hele byen, for eksempel når du analyserer tilgjengeligheten av jobber og tjenester (som i reisetidsmatrisedataene som ble brukt i tidligere seksjoner).
Sjekk ut pyrosm-dokumentasjonen om arbeid med grafer for mer avanserte eksempler på nettverksanalyse i python. For eksempel er pandana et raskt og effektivt python-bibliotek for å lage aggregerte nettverksanalyser på kort tid over store nettverk, og pyrosm kan brukes til å forberede inngangsdataene for en slik analyse.