Which countries have better cycle infrastructure?
There is a new trend to have a good cycle infrastructure. But not all countries can boast about it. For example, all know about the Netherlands, which population is less than the number of bicycles. I decided to analyze the cycle infrastructure of European countries. For this, I took spatial data from Open Street Map and visualized it.
OpenStreetMap, also called as OSM, has many spatial data, which gather thousands of users from around the world. We can find here lots of interesting information.
In addition to this, this data is open to downloading and we can use OSM API for receiving spatial features.
I’ve used osmdata package for this. But I had to take into account the limits of api, so I modified the function to download data.
I loaded the data one by one in latitude, so as not to exceed the download limits of the data. My function os divide data into parts, which then, after transforming into a data table (I used for this fortify function from ggplot2 package), were merged into one large table. Fortify-function makes the data suitable for visualization in ggplot2.
It took me half a day.
require(osmdata)
require(ggplot2)
require(dplyr)
os <- function() {
b <- combn(-10:50,2) %>% t()
b <- b[!duplicated(b[,1]),]
cw <- opq(bbox = c(b[1,1], 35, b[1,2], 70),
timeout = 125, memsize = 100000000) %>%
add_osm_feature(key = 'highway', value = 'cycleway')
cwmap <- osmdata_sp(cw)
xdf <- fortify(cwmap$osm_lines)
cat(paste0(round(i/nrow(b),2)*100,"% \n"))
for(i in 2:nrow(b)) {
cw <- opq(bbox = c(b[i,1], 35, b[i,2], 70),
timeout = 125, memsize = 100000000) %>%
add_osm_feature(key = 'highway', value = 'cycleway')
cwmap <- osmdata_sp(cw)
xdf <- rbind(xdf, fortify(cwmap$osm_lines))
cat(paste0(round(i/nrow(b),2)*100,"% \n"))
}
xdf
}
cyclemap <- os()
I got the following dataset:
head(cyclemap) %>% gt::gt()
.id | long | lat | order | piece | id | group |
---|---|---|---|---|---|---|
24783150 | -9.450528 | 53.44152 | 1 | 1 | 24783150 | 24783150.1 |
24783150 | -9.450343 | 53.44161 | 2 | 1 | 24783150 | 24783150.1 |
24783150 | -9.450218 | 53.44182 | 3 | 1 | 24783150 | 24783150.1 |
24783150 | -9.450209 | 53.44187 | 4 | 1 | 24783150 | 24783150.1 |
24783150 | -9.450190 | 53.44196 | 5 | 1 | 24783150 | 24783150.1 |
24783150 | -9.450343 | 53.44213 | 6 | 1 | 24783150 | 24783150.1 |
It had 7421025 observations and 7 variables.
dplyr::glimpse(cyclemap, width = 60)
Observations: 7,421,025
Variables: 7
$ .id <chr> "24783150", "24783150", "24783150", "247831…
$ long <dbl> -9.450528, -9.450343, -9.450218, -9.450209,…
$ lat <dbl> 53.44152, 53.44161, 53.44182, 53.44187, 53.…
$ order <int> 1, 2, 3, 4, 5, 6, 1, 2, 1, 2, 3, 4, 5, 6, 7…
$ piece <fct> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
$ id <dbl> 24783150, 24783150, 24783150, 24783150, 247…
$ group <fct> 24783150.1, 24783150.1, 24783150.1, 2478315…
Now that I’ve got the data, I can make visualization.
There is no alternative to this - ggplot2.
I wanted to achieve the effect of the glow from space, so used dark background tones (I made a black fill for the countries and dark gray fill for seas and oceans).
Also, I used gilbert’s projection for the edge because this projection does not stretch the poles so much as the Mercator-projection.
ggplot() +
borders("world", xlim = c(-10, 50),
ylim = c(20, 70), size= 0.05,
fill = "black") + #add coutries borders
geom_path(data = cyclemap,
aes(long, lat, group = group),
size = 0.01, color = "white") +
coord_map("gilbert",
xlim = c(-10, 50), ylim = c(33, 71)) +
geom_text(aes(x=-20, y = 70,
label = "European map of cycle paths",
hjust = 0, vjust=1),
family = "PT Sans", color = "white", size = 4)+
geom_text(aes(x=-20, y = 68.6,
label = " Based on OSM data",
hjust = 0, vjust = 1),
family = "PT Sans", color = "white", size = 3)+
theme_void() +
theme(
plot.background = element_rect(fill = "#252525",
colour = "#252525")
)