Ich zeige in diesem Beitrag wie man mit deckgl in R kartenbasierte Streudiagramme erzeugen kann.
Eine Voraussetzung für die Verwendung von deckgl zur Visualisierung von räumlichen bzw. ortsbezogenen Daten ist, dass jeder Observation Koordinaten in Form von Longitude und Latitude zugeordnet werden. Sollten diese Koordinaten noch nicht vorliegen so kann hierfür die Open Street Map API verwendet werden.
Die Open Street Map API empfängt bspw. Ortsnamen als Strings und retourniert Koordinaten in JSON-Format. Zur Auswertung der Rückmeldungen empfiehlt sich also die Anwendung des jsonlite-Pakets.
Nachstehend habe ich eine Funktion implementiert, welche ich von datascienceplus.com übernommen habe. Die Funktion übergibt Adressen an die OSM API und empfängt die Rückmeldungen der OSM API. Diesen Prozess bezeichne ich als „Geocoding“
# osm geocoding
# 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)))
}
In einer csv-Datei habe ich eine Liste von Ortsnamen hinterlegt. Ich lese diese Liste ein, führe den „Geocoding“-Prozess für jeden Ortsnamen durch und speichere Ortsnamen mit dazugehörigen Koordinaten in einer DataFrame-Tabelle ab. Daraufhin ordne ich jedem Ortsnamen einen Zufallsverteilten Observationswert zu. Dieser wird den Durchmesser der Kreise im späteren Streudiagramm bestimmen:
# relevante Pakete einlesen
library(deckgl)
library(magrittr)
library(jsonlite)
library(dplyr)
# dataframe erzeugen
scatter_data_df_1 <- data.frame(matrix(nrow=30,ncol=6))
column_names <- c("name","code","address","entries","exits","coordinates")
colnames(scatter_data_df_1) <- column_names
city_list_1_df <- read.csv("city list 1.csv",header = FALSE, stringsAsFactors = FALSE)
# geocoding für jeden ortsnamen in der liste durchführen
for(i in 1:nrow(city_list_1_df)){
dum_coord <- osm_geocoder(toString(city_list_1_df$V1[i]))
scatter_data_df_1$name[i] <- paste0("city liste 1 : ",i)
scatter_data_df_1$code[i] <- c("CL1")
scatter_data_df_1$address[i] <- toString(city_list_1_df$V1[i])
scatter_data_df_1$entries[i] <- as.integer(rnorm(1,mean=3000,sd=1000))
scatter_data_df_1$exits[i] <- as.integer(rnorm(1,mean=3000,1000))
scatter_data_df_1$coordinates[i] <- list(c(as.numeric(dum_coord[1]),as.numeric(dum_coord[2])))
}
# kopf der dataframe-tabelle ausgeben
head(scatter_data_df_1)
## name code address entries exits
## 1 city liste 1 : 1 CL1 Berlin Germany 5008 3112
## 2 city liste 1 : 2 CL1 Karlsruhe Germany 2002 2223
## 3 city liste 1 : 3 CL1 Stuttgart Germany 3453 3498
## 4 city liste 1 : 4 CL1 Mannheim Germany 2478 3041
## 5 city liste 1 : 5 CL1 Heidelberg Germany 3811 1003
## 6 city liste 1 : 6 CL1 Frankfurt Germany 1875 3135
## coordinates
## 1 13.38886, 52.51704
## 2 8.40342, 49.00687
## 3 9.180013, 48.778449
## 4 8.467236, 49.489591
## 5 8.694724, 49.409358
## 6 8.682092, 50.110644
Ich kann nun ein Streudiagramm mit deckgl in R erzeugen:
# eigenschaften des streudiagramms festlegen
properties_1 <- list(
getPosition = get_property("coordinates"),
getRadius = JS("data => Math.sqrt(data.exits)"),
radiusScale = 1000,
getColor = c(255, 153, 77)
)
# streudiagramm erzeugen bzw. darstellen
deckgl(zoom = 10.5, pitch = 35, longitude = 8.40342, latitude = 40.00687) %>%
add_scatterplot_layer(data = scatter_data_df_1, properties = properties_1) %>%
add_mapbox_basemap(style = "mapbox://styles/linnartsf/cjq6p9q8f8zwf2rp74qf2o3d5")
Es entsteht so nachstehendes Streudiagramm:


Wirtschaftsingenieur mit Interesse an Optimierung, Simulation und mathematischer Modellierung in R, SQL, VBA und Python
Leave a Reply