Ricerca Sociale con R

Una wiki per l'analisi dei dati con R

Strumenti Utente

Strumenti Sito


r:ggplot2:openstreetmap

Mappe con i dati di OpenStreetMap

OpenStreetMap (OSM) è un progetto collaborativo finalizzato a creare mappe del mondo a contenuto libero. Il progetto punta ad una raccolta mondiale di dati geografici, con scopo principale la creazione di mappe e cartografie.
La caratteristica fondamentale dei dati geografici presenti in OSM è che vengono distribuiti con una licenza libera, la Open Database License: è cioè possibile utilizzarli liberamente per qualsiasi scopo, anche commerciale, con il solo vincolo di citare la fonte e usare la stessa licenza per eventuali lavori derivati dai dati di OSM. (OpenStreetMap)

Per usare i dati di OpenStreetMap, usiamo le funzioni del pacchetto osmdata:

# installazione
install.packages("osmdata")

I pacchetti che servono nel seguito sono:

library(tidyverse)
library(sf)
library(osmdata)

La query

Come prima cosa, cerchiamo i limiti spaziali dei dati che vogliamo utilizzare, la bounding box (bbox), una area definita da due valori di longitudine e latitudine (https://wiki.openstreetmap.org/wiki/Bounding_Box).

# bounding box
bb <- getbb("Teramo")
bb
         min      max
  x 13.34693 14.14632
  y 42.42112 42.89508

I tipi di dati (features) disponibili su OSM sono consultabili alla pagina https://wiki.openstreetmap.org/wiki/IT:Map_Features, oppure attraverso il comando available_features(), e per ciascuna classe, con available_tags().

Se ad esempio siamo interessati ai dati sui luoghi per il tempo libero (feature = leisure), possiamo vedere cosa comprendono con il comando:

available_tags("leisure")
 [1] "adult_gaming_centre" "amusement_arcade"    "bandstand"          
 [4] "beach_resort"        "bird_hide"           "common"             
 [7] "dance"               "disc_golf_course"    "dog_park"           
[10] "escape_game"         "firepit"             "fishing"            
[13] "fitness_centre"      "fitness_station"     "garden"             
[16] "golfcourse"          "hackerspace"         "horse_riding"       
[19] "ice_rink"            "marina"              "miniature_golf"     
[22] "nature_reserve"      "park"                "picnic_table"       
[25] "pitch"               "playground"          "slipway"            
[28] "sports_centre"       "stadium"             "summer_camp"        
[31] "swimming_area"       "swimming_pool"       "track"              
[34] "water_park"         

componiamo la query con la funzione opq() (overpass query), applicata alla bbox del territorio che ci interessa (bb), e aggiungiamo le feature alla quesry (con add_osm_feature("leisure")):

q <- opq(bb) %>% 
  # feature
  add_osm_feature("leisure")

Importiamo i dati in formato sf (vedi Rappresentare i dati geografici):

sf.data <- osmdata_sf(q)

Il risultato è una lista che contiene i seguenti elementi:

names(sf.data)
[1] "bbox"              "overpass_call"     "meta"             
[4] "osm_points"        "osm_lines"         "osm_polygons"     
[7] "osm_multilines"    "osm_multipolygons"

Rappresentare i dati in una mappa

Utilizziamo in questo caso i dati relativi ai punti (sf.data$osm_points), e costruiamo una mappa (vedi voce):

ggplot() +
  geom_sf(data = sf.data$osm_points,
          col = "darkblue") 

I dati che abbiamo scaricato riguardano l'intera area della della bbox, e non i confini del territorio (provincia di Teramo).

Usiamo i confini amministrativi disponibili sul sito dell’Istat (vedi voce):

library(readr)
prov2020 <- st_read("ProvCM01012020_g")
ggplot() +
  # solo la provincia di Teramo, con filter
  geom_sf(data =filter(prov2020, COD_PROV == 67)) +
  geom_sf(data = sf.data$osm_points,
          col = "darkblue") + 
  # tema vuoto
  theme_void()

Per aggiungere delle etichette alla mappa (Vedi voce), possiamo usare uno dei campi del dataset:

names(sf.data$osm_points) %>% head()
  [1] "osm_id"           "name"             "access"           "addr.city"       
  [5] "addr.housenumber" "addr.postcode"   

Aggiungere uno sfondo

In questo momento, gli sfondi liberamente scaricabili sono quelli di Stamen. Possono essere scaricati con il pacchetto ggmap, pensato principalmente per le mappe di Google Maps.

library(ggmap)

Scarichiamo lo sfondo stile "terrain", quello tipico delle mappe fisiche, ma senza i nomi ('terrain-background'), utilizzando i limiti dell'area precedente:

ter_map <- get_stamenmap(bb,                # bbox ottenuto con il pacchetto osmdata
              maptype='terrain-background')

Queste mappe possono essere stampate con la funzione ggmap()

ggmap(ter_map)

Per aggiungere questa mappa a quella precedente, faremo prima di tutto attenzione all'ordine (lo sfondo in basso, poi i confini, poi i punti):

ggmap(ter_map) +
  # confini della provincia
  geom_sf(data =filter(prov2020, COD_PROV == 67),
          # area trasparente, perché c'è lo sfondo sotto
          alpha = 0, 
          # colore e dimensione del bordo
          col = "red", size = 1,
          # ignora aes di ggmap
          inherit.aes = FALSE) +

Poiché i sistemi di rappresentazione delle coordinate sono diversi, dobbiamo specificare l'argomento inherit.aes = FALSE per ogni set di dati, e, alla fine, specificare il sistema di riferimento (in questo caso l'EPSG:4326, che sarebbe lo standard, ma non è quello usato da ggmap).

# punti
geom_sf(data = sf.data$osm_points,
        col = "darkblue", size = 0.8,
        inherit.aes = FALSE) + 
  # coordinate reference systems 
  coord_sf(crs=sf::st_crs(4326)) +
  theme_void()

Script di esempio

OpenStreetMap.R
# installazione
install.packages("osmdata")
library(tidyverse)
library(sf)
library(osmdata)
 
# bounding box
bb <- getbb("Teramo")
 
# query
q <- # overpass query
   opq(bb) %>% 
   # feature
   add_osm_feature("leisure")
 
# scaricare i dati
sf.data <- osmdata_sf(q)
 
# mappa
ggplot() +
  geom_sf(data = sf.data$osm_points,
          col = "darkblue")
 
# con i dati Istat
library(readr)
prov2020 <- st_read("ProvCM01012020_g")
 
ggplot() +
  # solo la provincia di Teramo, con filter
  geom_sf(data =filter(prov2020, COD_PROV == 67)) +
  geom_sf(data = sf.data$osm_points,
          col = "darkblue") + 
  # tema vuoto
  theme_void()
osm_ggmap.R
library(tidyverse)
library(sf)
library(osmdata)
library(ggmap)
 
# bounding box
bb <- getbb("Teramo")
 
# sfondo
ter_map <- get_stamenmap(bb,               
              maptype='terrain-background')
# mappa
ggmap(ter_map)
 
# mappa e dati OpenStreetMap
ggmap(ter_map) +
  geom_sf(data = sf.data$osm_points,
          col = "darkblue", size = 0.8,
          inherit.aes = FALSE) + 
    # coordinate reference systems 
    coord_sf(crs=sf::st_crs(4326)) +
    theme_void()

Domande? Scrivimi

Messenger Telegram Email
r/ggplot2/openstreetmap.txt · Ultima modifica: 05/09/2025 16:48 da Agnese Vardanega