Visualisierung räumlicher Daten mit deckgl in R

Nachstehend folgt ein Beispiel zur Visualisierung räumlicher Daten mittels kartenbasierten 3D Graphiken in R. Solche Visualisierungen können mit dem deckgl Paket erzeugt werden. Die Karten dienen als Hintergrund und müssen bspw. auf Mapbox (https://www.mapbox.com/) erzeugt und ggf. konfiguriert werden.

Zunächst implementiere ich eine Funktion die ich für das “Geocoding” meiner Daten anwenden möchte, d.h. der Zuordnung von Koordinaten anhand von bspw. Ortsnamen oder Adressen. Nachstehende Funktion verwendet eine API von Open Street Map (https://www.openstreetmap.org) welche Koordinaten in JSON-Format retourniert. Die Funktion habe ich von datascienceplus.com übernommen.

## dokumentation: http://wiki.openstreetmap.org/wiki/Nominatim
# quelle: https://datascienceplus.com/osm-nominatim-with-r-getting-locations-geo-coordinates-by-its-address/
osm_geocoder <- function(address = NULL)
{
  if(suppressWarnings(is.null(address)))
    return(data.frame())
  
  tryCatch(
    d <- jsonlite::fromJSON( 
      gsub('\\@addr\\@', gsub('\\s+', '\\%20', address), 
           'http://nominatim.openstreetmap.org/search/@addr@?format=json&addressdetails=0&limit=1')
    ), error = function(c) return(data.frame())
  )
  
  if(length(d) == 0) 
    return(data.frame())
  
  return(data.frame(lon = as.numeric(d$lon), lat = as.numeric(d$lat)))
}

Nachdem ich die Funktion für das “Geocoding” erstellt habe erzeuge ich für Demonstrationszwecke einen Vektor mit Ortsnamen im deutschsprachigen Raum. Mit der soeben implementierten Funktion ordne ich den Ortsnamen Koordinaten zu. Daraufhin ordne ich jedem Ortsnamen auch noch einen normalverteilten (d.h. zufälligen) Zielwert zu, für gemäss Normalverteilung zufällig generierten Koordinatenpunkten in unmittelbarer Nähe zu dem jeweiligen Ortsnamen:

city_list <- c("Frankfurt, Germany",
               "Dortmund, Germany",
               "Berlin, Germany",
               "Stuttgart, Germany",
               "Karlsruhe, Germany",
               "Zurich, Switzerland", 
               "Wien, Austria", 
               "Bern, Switzerland",
               "Munich, Germany",
               "Marburg, Germany",
               "Giessen, Germany",
               "Pforzheim, Germany",
               "Cologne, Germany", 
               "Essen, Germany", 
               "Heidelberg, Germany",
               "Kassel, Germany",
               "Paderborn, Germany",
               "Leipzig, Germany",
               "Dresden, Germany",
               "Nuremberg, Germany",
               "Augsburg, Germany",
               "Regensburg, Germany",
               "Pilsen, Czech Republic",
               "Linz, Austria",
               "Innsbruck, Austria",
               "Bamberg, Germany",
               "Fulda, Germany",
               "Hanover, Germany",
               "Wolfsburg, Germany",
               "Magdeburg, Germany",
               "Jena, Germany",
               "Chemnitz, Germany",
               "Zwickau, Germany",
               "Cottbus, Germany",
               "Bautzen, Germany",
               "Mainz, Germany",
               "Bonn, Germany",
               "Duesseldorf, Germany",
               "Trier, Germany",
               "Mannheim, Germany",
               "Aachen, Germany",
               "Freiburg, Germany",
               "Ulm, Germany",
               "Kempten, Germany",
               "Ingolstadt, Germany")

# daten zum testen erzeugen
data_df_columns <- data.frame(matrix(nrow=3500*length(city_list),ncol=4))
colnames(data_df_columns) <- c("ADDRESS","RACKS","SPACES","COORDINATES")

data_df_columns$RACKS <- 2
data_df_columns$SPACES <- 4

for(i in 1:length(city_list)){
  print(i)
  dum_coord <- osm_geocoder(city_list[i])
  for(j in 1:3500){
    data_df_columns$ADDRESS <- paste0(city_list[i]," : ",j)
    dum_long <- rnorm(1, mean=as.numeric(dum_coord[1]),sd=0.75)  
    dum_lat <- rnorm(1,mean=as.numeric(dum_coord[2]),sd=0.75)
    data_df_columns$COORDINATES[(i-1)*3500+j] <- list(c(dum_long, dum_lat))
  }
}

properties_grid <- list(
  pickable = TRUE,
  extruded = TRUE,
  cellSize = 1600,
  elevationScale = 8,
  coverage = 0.5,
  colorRange = list(c(0,255,255),
                    c(0,204,255),
                    c(0,153,255),
                    c(0,51,255),
                    c(0,0,255),
                    c(0,0,204)),
  getPosition = JS("data => data.COORDINATES"),
  getTooltip = JS("object => object.count")
)

Nachdem ich mein DataFrame mit zufälligen Zielwerten je Ortsnamen erzeugt habe verwende ich das deckgl Paket in R um die örtliche bzw. räumliche Intensität meiner Zielwertverteilung darzustellen. Die Basiskarte stammt von Mapbox:

deckgl(zoom = 10, pitch = 120, longitude = 8.682092, latitude = 50.11064) %>%
  add_grid_layer(data = data_df_columns,properties = properties_grid) %>%
  add_mapbox_basemap(style = "mapbox://styles/linnartsf/cjq6p9q8f8zwf2rp74qf2o3d5")
Intensität der örtlichen Zielwertverteilung in deckgl dargestellt

You May Also Like

Leave a Reply

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.