The Overpass API provides access to the data behind the Openstreetmaps Map Data. The Overpass-Turbo is the easyiest way to test requests and get the correct code to ask the database.
import pandas as pd
import requests
import json
pd.set_option('display.max_columns', 200)
Annahme: Eine Kreuzung ist dadurch definiert, dass es ein Node
gibt, der mindestens zu 2 verschiedenen highways
gehört.
Gebiet festlegen, am besten mit einer Bounding Box
# Get yours at: http://boundingbox.klokantech.com/
bbox = [13.521945,50.919085,13.976063,51.18772]
# Links unten
minLat = bbox[1]
minLon = bbox[0]
# Rechts oben
maxLat = bbox[3]
maxLon = bbox[2]
Request from Overpass-Turbo
tags = ['primary','secondary','secondary_link','tertiary','tertiary_link','living_street','residential']
objects = ['way'] # like way, node, relation
compactOverpassQLstring = '[out:json][timeout:60];('
for tag in tags:
for obj in objects:
compactOverpassQLstring += '%s["highway"="%s"](%s,%s,%s,%s);' % (obj, tag, minLat, minLon, maxLat, maxLon)
compactOverpassQLstring += ');out body;>;out skel qt;'
osmrequest = {'data': compactOverpassQLstring}
osmurl = 'http://overpass-api.de/api/interpreter'
# Ask the API
osm = requests.get(osmurl, params=osmrequest)
The JSON can't be directyl imported to a Pandas Dataframe:
Thanks to unutbu from stackoverflow.com for fiddling this out!
osmdata = osm.json()
osmdata = osmdata['elements']
for dct in osmdata:
if dct['type']=='way':
for key, val in dct['tags'].iteritems():
dct[key] = val
del dct['tags']
else:
pass # nodes
osmdf = pd.DataFrame(osmdata)
osmdf.tail(5)
FIXME | access | access:N3 | access:conditional | access:lanes | addr:city | addr:country | addr:postcode | addr:street | addr:suburb | agricultural | alt_name | amenity | area | area:highway | bicycle | bicycle:backward | bicycle:forward | bridge | bridge_name | bridge_type | bus | bus:lanes:backward | bus:lanes:forward | busway:right | change:lanes:backward | change:lanes:forward | class:bicycle | collection_times | comment | comment:history | construction | construction:end | construction:obstruction | construction:start | covered | created_by | cutting | cycleway | cycleway:bicycle | cycleway:foot | cycleway:forward | cycleway:left | cycleway:left:bicycle | cycleway:left:foot | cycleway:oneway | cycleway:right | cycleway:right:bicycle | cycleway:right:oneway | cycleway:right:segregated | cycleway:right:smoothness | cycleway:right:surface | cycleway:segregated | cycleway:smoothness | day_off | day_on | delivery | description | designation | destination | destination:backward | destination:forward | destination:lanes | destination:lanes:forward | destination:ref | destination:ref:backward | disused:highway | electrified | embankment | est_width | fake_gaslight | fixme | flood_prone | foot | footway | footway:left | footway:right | forestry | frequency | gauge | goods | hazmat:backward | hazmat:forward | hgv | hgv:backward | hgv:conditional | hgv:forward | hgv:hazard | highway | historical_name | history | horse | hour_off | hour_on | id | image | incline | int_name | int_ref | is_in | ... | motorroad | mtb | mtb:scale | mtb:scale:uphill | name | name:be | name:de | name:es | narrow | nat_ref | nodes | noexit | note | note:FIXME | note:maxheight | old_name | old_name:1897 | oneway | oneway:bicycle | overtaking | overtaking:hgv | parking:condition:both | parking:condition:both:maxstay | parking:condition:both:time_interval | parking:condition:left | parking:condition:left:fee_per_hour | parking:condition:left:maxstay | parking:condition:left:time_interval | parking:condition:maxstay | parking:condition:right | parking:condition:right:fee_per_hour | parking:condition:right:maxstay | parking:condition:right:time_interval | parking:condition:right:vehicles | parking:lane | parking:lane:both | parking:lane:left | parking:lane:left:capacity | parking:lane:left:parallel | parking:lane:right | parking:lane:right:capacity | parking:lane:right:diagonal | parking:lane:right:parallel | placement | planned | postal_code | psv | railway | ref | segregated | service | short_name | sidewalk | sidewalk:right | smoking | smoothness | source | source:highway | source:maxheight | source:maxspeed | source:maxspeed:backward | source:maxspeed:conditional | source:maxspeed:forward | source:maxspeed:hgv | source:name | source:surface | source:width | source_ref | surface | surface:left | surface:right | taxi | tracks | tracktype | traffic_calming | traffic_sign | tram:lanes:backward | tram:lanes:forward | tree_lined | tunnel | turn | turn:lanes | turn:lanes:backward | turn:lanes:forward | type | vehicle | vehicle:backward | vehicle:forward | vehicle:forward:conditional | voltage | wheelchair | width | wikipedia | wikipedia:de | xmas:day_date | xmas:feature | xmas:name | xmas:opening_hours | zone:maxspeed | zone:traffic | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
100538 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 390316202 | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | node | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
100539 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1841220477 | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | node | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
100540 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 60619766 | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | node | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
100541 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 60619767 | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | node | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
100542 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 457976561 | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | node | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
5 rows × 252 columns
for tag in osmdf.highway.unique():
print tag
residential living_street secondary tertiary primary secondary_link tertiary_link nan
for tag in osmdf.maxspeed.unique():
print tag
30 nan 50 70 60 100 20 40 5 80 10 walk 7 8 5 mph
Nur ways behalten, die auch als highway
gekennzeichnet sind und einen Namen haben.
highwaydf = osmdf[['id', 'highway', 'lanes', 'name', 'maxspeed', 'nodes', 'ref']].dropna(subset=['name','highway'], how='any')
highwaydf.tail(5)
id | highway | lanes | name | maxspeed | nodes | ref | |
---|---|---|---|---|---|---|---|
16374 | 293501216 | secondary | NaN | Tiergartenstraße | 50 | [373247978, 373247792, 373247777, 373247621, 2... | NaN |
16375 | 293501217 | secondary | NaN | Tiergartenstraße | 50 | [2971077364, 18630288, 796746061, 796746056, 3... | NaN |
16376 | 293509214 | residential | NaN | Lockwitzbachweg | NaN | [773905499, 2693555506, 2261360369, 206122406] | NaN |
16377 | 293808792 | residential | NaN | Talstraße | NaN | [2973933926, 2973933927] | NaN |
16378 | 293808793 | residential | NaN | Talstraße | NaN | [2973933927, 304417978] | NaN |
Zu kleine Straßen raus werfen
highwaydf = highwaydf[highwaydf['highway'].isin(tags)]
Replace NaN
with word unknown
and reset the index
highwaydf = highwaydf.fillna(u'unknown').reset_index(drop=True)
highwaydf.tail(5)
id | highway | lanes | name | maxspeed | nodes | ref | |
---|---|---|---|---|---|---|---|
14645 | 293501216 | secondary | unknown | Tiergartenstraße | 50 | [373247978, 373247792, 373247777, 373247621, 2... | unknown |
14646 | 293501217 | secondary | unknown | Tiergartenstraße | 50 | [2971077364, 18630288, 796746061, 796746056, 3... | unknown |
14647 | 293509214 | residential | unknown | Lockwitzbachweg | unknown | [773905499, 2693555506, 2261360369, 206122406] | unknown |
14648 | 293808792 | residential | unknown | Talstraße | unknown | [2973933926, 2973933927] | unknown |
14649 | 293808793 | residential | unknown | Talstraße | unknown | [2973933927, 304417978] | unknown |
nodes = []
for dct in osmdata:
#print dct
if dct['type']=='way':
pass
elif dct['type']=='node':
nodes.append(dct)
else:
pass
nodesdf = pd.DataFrame(nodes)
nodesdf.tail(5)
id | lat | lon | type | |
---|---|---|---|---|
84159 | 390316202 | 51.188021 | 13.933286 | node |
84160 | 1841220477 | 51.188789 | 13.968988 | node |
84161 | 60619766 | 51.187108 | 13.967311 | node |
84162 | 60619767 | 51.189634 | 13.969590 | node |
84163 | 457976561 | 51.188113 | 13.968319 | node |
Jeden Knoten durch gehen und schauen, ob er bei einer Straße genutzt wird. Wenn ja, die Straßen IDs zurück geben.
def gethighwayids(nodeid):
highwayids = []
for n, nodes in enumerate(highwaydf['nodes']):
for nid in nodes: # alle nodes des highways
if nid == int(nodeid):
highwayids.append(highwaydf['id'][n])
return highwayids
Dauert sehr sehr lang, wenn BoundingBox groß gewählt wurde!
nodesdf['highwayids'] = nodesdf['id'].apply(gethighwayids)
nodesdf.head(10)
id | lat | lon | type | highwayids | |
---|---|---|---|---|---|
0 | 32456409 | 50.924436 | 13.525700 | node | [] |
1 | 87215458 | 50.921920 | 13.521153 | node | [10313904] |
2 | 87215459 | 50.921850 | 13.521617 | node | [10313904] |
3 | 87215462 | 50.921374 | 13.524183 | node | [10313904] |
4 | 87215463 | 50.921254 | 13.525067 | node | [10313904] |
5 | 87215464 | 50.921168 | 13.525685 | node | [10313904] |
6 | 87215465 | 50.921135 | 13.526123 | node | [10313904] |
7 | 614864158 | 50.921536 | 13.523308 | node | [10313904] |
8 | 32456411 | 50.923717 | 13.523962 | node | [] |
9 | 32456413 | 50.923199 | 13.522634 | node | [] |
Node with at least 3 different highways
def identifyjunction(highwayids):
#print highwayids
if len(highwayids) < 2:
return False
elif len(highwayids)==2:
# Wenn beide Highways den gleichen Namen haben, ist es nur
# ein Zwischenstück und keine Kreuzung
name1=unicode(highwaydf[highwaydf['id']==highwayids[0]]['name'].values)
name2=unicode(highwaydf[highwaydf['id']==highwayids[1]]['name'].values)
if name1==name2:
#print('%s=%s' % (name1, name2))
return False
else:
return True
else:
return True
nodesdf['junction'] = nodesdf['highwayids'].apply(identifyjunction)
nodesdf.tail(10)
id | lat | lon | type | highwayids | junction | |
---|---|---|---|---|---|---|
84154 | 260131313 | 51.187867 | 13.907815 | node | [23992944] | False |
84155 | 260131314 | 51.187750 | 13.908055 | node | [23992944] | False |
84156 | 115777097 | 51.187300 | 13.932714 | node | [168364168] | False |
84157 | 115776949 | 51.190797 | 13.933067 | node | [168364168] | False |
84158 | 115777099 | 51.188737 | 13.933498 | node | [168364168] | False |
84159 | 390316202 | 51.188021 | 13.933286 | node | [168364168] | False |
84160 | 1841220477 | 51.188789 | 13.968988 | node | [173268928] | False |
84161 | 60619766 | 51.187108 | 13.967311 | node | [173268928, 173453037] | False |
84162 | 60619767 | 51.189634 | 13.969590 | node | [173268928] | False |
84163 | 457976561 | 51.188113 | 13.968319 | node | [173268928] | False |
junctionsdf = nodesdf[['id','lat','lon']][nodesdf['junction']==True]
junctionsdf.to_csv('junctions.csv', index=False)
print('done.')
done.