I like to plot streets with ggmap
in a specific area. I got the data from osm via the overpass api. It works pretty good for most streets with geom_path
. However, some streets are messed up. Any hints are appreciated.
Please have a look at http://overpass-turbo.eu/ for the desired output. You can find the query in the R-code below.
library(httr)
library(tidyverse)
#> ── Attaching packages ─────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
#> ✔ ggplot2 2.2.1 ✔ purrr 0.2.4
#> ✔ tibble 1.4.2 ✔ dplyr 0.7.4
#> ✔ tidyr 0.8.0 ✔ stringr 1.3.0
#> ✔ readr 1.1.1 ✔ forcats 0.3.0
#> ── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ dplyr::filter() masks stats::filter()
#> ✖ dplyr::lag() masks stats::lag()
library(ggmap)
library(rlist)
# Get data from overpass api
query <- paste('[out:json];',
'(way["highway"~"primary|residential"](53.5970, 9.9010, 53.6050, 9.9080););',
'(._;>;);',
'out body;')
url <- 'http://overpass-api.de/api/interpreter'
r <- POST(url = url, body = query, encode = 'json')
# Tidy data
nodes <- content(r)$elements %>% list.filter(type == 'node')
ways <- content(r)$elements %>% list.filter(type == 'way')
df_nodes <- nodes %>%
list.select(type, id, lat, lon) %>%
bind_rows()
df_ways <- ways %>%
lapply(function(x) list.append(x, street = x$tags$name)) %>%
list.select(street, nodes)
df_ways <- map(df_ways, function(x) x %>% as_tibble) %>%
bind_rows() %>%
mutate(id = unlist(nodes))
df <- df_ways %>% left_join(df_nodes, by = 'id')
head(df)
#> # A tibble: 6 x 6
#> street nodes id type lat lon
#> <chr> <list> <dbl> <chr> <dbl> <dbl>
#> 1 Reichsbahnstraße <int [1]> 38893884 node 53.6 9.91
#> 2 Reichsbahnstraße <int [1]> 55079985 node 53.6 9.91
#> 3 Reichsbahnstraße <int [1]> 38893882 node 53.6 9.91
#> 4 Reichsbahnstraße <int [1]> 38893881 node 53.6 9.91
#> 5 Reichsbahnstraße <int [1]> 380820539 node 53.6 9.91
#> 6 Reichsbahnstraße <int [1]> 38893879 node 53.6 9.91
# Get map
lat <- (max(df$lat)+min(df$lat))/2
lon <- (max(df$lon)+min(df$lon))/2
hamburg <- get_map(location = c(lon = lon, lat = lat), zoom = 16)
#> Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=53.601726,9.90531&zoom=16&size=640x640&scale=2&maptype=terrain&language=en-EN&sensor=false
# Plot
ggmap(hamburg) +
geom_path(data = df, aes(x = lon, y = lat, color = street), size = 2)
#> Warning: Removed 3 rows containing missing values (geom_path).
You will have this issue whenever the street has many branches, since geom_path()
will simply link each two consecutive points with a straight line.
Let's take 'Reichsbahnstraße' as an example:
lon <- df %>% filter(street == "Reichsbahnstraße") %>% .$lon
lat <- df %>% filter(street == "Reichsbahnstraße") %>% .$lat
lat[1] == lat[41] & lon[1] == lon[41]
# returns TRUE
geom_path()
starts from point 1 (the intersection point, see bellow), draws one part of the street (going to the north east), and then comes back to the intersection point again (index 41) to draw the next branch.
What you can do to avoid this is go back to the intersection point through the same road, before drawing the other branch (e.g. instead of c(7, 8, 9, 10, 7, 6)
do c(7, 8, 9, 10, 9, 8, 7, 6)
). Kind of like what you would do if you were trying to draw the street with a pencil without lifting it off the paper sheet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With