ggplot2 Erweiterungen: Diagramme kombinieren, Kartenerstellung und interaktive Grafiken

Data Science 1 - Programmieren & Visualisieren

Saskia Otto & Monika Eberhard

Universität Hamburg, IMF

Wintersemester

Lernziele

Am Ende dieser VL- und Übungseinheit werden Sie

  • mehrere ggplot2 Diagramme mit dem Paket patchwork kombinieren können.
  • verschiedene Arten thematischer Karten unterscheiden können.
  • Karten aus Geodaten im sf-Format mit ggplot2 und geom_sf() erstellen können – mit frei verfügbaren Daten aus rnaturalearth und OpenStreetMap.
  • statische ggplot2-Diagramme zu interaktiven plotly-Grafiken konvertieren können.
  • interaktive Karten mit dem Paket leaflet erstellen können.

Diagramme kombinieren

Übersicht an R Paketen

  • Für ggplot-Objekte funktionieren die Standard R Funktionen par() und layout() nicht.
  • Hilfreiche Pakete:
    • patchwork → modern, intuitive Syntax mit +, / und | – das nutzen wir
    • cowplot → plot_grid(), ggdraw() + draw_plot(); freie Platzierung über Koordinaten (0–1)
    • gridExtra → grid.arrange(); älter, aber robust, z.B. zum Mischen von Diagrammen mit Tabellen

In vielen älteren Skripten und Foren-Antworten finden Sie noch cowplot oder gridExtra. Alles, was wir heute zeigen, lässt sich aber auch mit patchwork umsetzen.

Demo-Diagramme

Jede Herangehensweise wird mit 3 verschiedenen Diagrammen vom bshydro15 Datensatz demonstriert:

Code
data(bshydro15, package = "marinedata")

summer <- bshydro15 |>
  mutate(month = factor(month.abb[month], levels = month.abb)) |> 
  filter(month %in% c("May", "Jun", "Jul", "Aug")) 

a <- summer |>
  filter(pres <= 5) |>
  select(sampling_id, month) |>
  distinct()  |>
  ggplot(aes(x = month)) +
  geom_bar(aes(fill = month)) +
  guides(fill = "none") +
  scale_fill_brewer(palette = "Set1") +
  guides(x = guide_axis(angle = 90)) +
  labs(x = "Month", y = "Measurements") +
  theme_classic()

b <- summer |> 
  group_by(ices_sd, station, lat, long, date_time, month, day) |>
  summarise(psal = mean(psal, na.rm = TRUE), .groups = "drop") |>
  drop_na() |> 
  ggplot(aes(x = long, y = psal, col = ices_sd)) +
  geom_point() +
  scale_colour_brewer(palette = "Paired") +
  guides(colour = "none") +
  labs(x = "Longitude", y = "Salinity") +
  theme_classic()

c <- summer |>
  filter(month %in% c("May", "Aug")) |>
  ggplot(aes(long,lat))+
  geom_point(aes(colour = temp)) +
  scale_colour_gradient(low = "white", high = "red") +
  facet_grid(. ~ month) +
  labs(x = "Longitude", y = "Latitude", col = "Temperature (°C)") +
  theme_classic()
a

Säulendiagramm - Anzahl der Messungen pro Sommermonat

b

Streudiagramm - Beziehung zwischen Längengrad & Salzgehalt (pro Teilgebiet)

c

Streudiagramm - Räumliche Verteilung der Oberflächen- temperaturen (Mai-August)

patchwork | Anordnen mit + und /

Nebeneinander mit +
library(patchwork)
a + b

Untereinander mit /
a / b

patchwork | Klammern und Layout

Klammern für komplexere Aufteilungen, plot_layout() für die Größenverhältnisse:

(a + b) / c +
  plot_layout(heights = c(1, 1.5))  # untere Zeile 1.5x so hoch

patchwork | Beschriftungen

Für Publikationen braucht man meist Teilbeschriftungen (a, b, c) und einen gemeinsamen Titel → plot_annotation()

(a + b) / c +
  plot_annotation(
    tag_levels = "a", tag_suffix = ")",  # a), b), c)
    title = "Ostsee-Oberflächendaten im Sommer 2015"
  )

patchwork | Verschachtelte Diagramme

  • Mit inset_element() wird ein kleines Diagramm in ein großes gesetzt.
  • Die Position wird über die Ränder des kleinen Diagramms angegeben (Werte von 0 bis 1 relativ zum Hauptdiagramm).
b + # Hauptdiagramm
  inset_element(a, 
    left = 0.45, bottom = 0.45,
    right = 0.95, top = 0.95)

Rasterspezifikationen in ‘npc’ Einheiten (0 = links/unten, 1 = rechts/oben)

patchwork | Speichern

  • Ein patchwork-Objekt ist weiterhin ein ggplot-Objekt → speichern wie gewohnt mit ggsave().
  • Wichtig: Breite und Höhe passend zur Anordnung wählen, sonst werden die Teildiagramme gestaucht.
abc <- (a + b) / c +
  plot_annotation(tag_levels = "a", tag_suffix = ")")

ggsave("abc.pdf", plot = abc,
  width = 20, height = 15, units = "cm")

Topografische vs. thematische Karten

Topografische Karten (Landkarten)

  • Dienen der Orientierung im Gelände und der Ausmessung von Standorten und anderen sichtbaren Details der Erdoberfläche.
  • Grundlage von Planungszwecken und Forschungsvorhaben.
  • Basis der meisten thematischen Karten.
  • Maßstab ist meist 1:25.000 bis 1:200.000.

Ausschnitt aus der topografischen USGS-Karte von Stowe, Vermont, USA (Maßstab 1:24.000).

Bildquelle: United States Geological Survey (CC0-Lizenz)

Thematische Karten (Kartogramme)

  • Zur Darstellung bestimmter Themen und Merkmale (z.B. Bevölkerungsdichte, Artverbreitung).
  • Darstellung von Zusammenhängen thematischer Ebenen (z.B. zeitliche Änderungen von Merkmalen wie Bevölkerungsdichte).
  • Wesentliche Eigenschaften: Sachbezug, Zeitbezug, Raumbezug
  • Darstellungsmittel: Punkte, Linien und Flächen (in Kombination)

Modell von geografischen Phänomenen sowie deren Visualisierungsmöglichkeiten

Flächenkartogramm, Choroplethenkarte

Durchschnittliches Vermögen pro Erwachsenem in US-Dollar im Jahr 2018, basierend auf dem Global Wealth Databook der Credit Suisse.
  • Gesammelte und typischerweise gruppierte Daten (z. B. nach Regionen) werden als Fläche durch Farben, Schattierungen oder Schraffierungen abhängig zum darzustellenden Wert abgebildet.
  • Je nach Art und Weise der Gruppierung (z. B. durch Mittelwertbildung, Median oder Summierung) kann das Ergebnis bzw. der Wert unterschiedlich sein.

Bildquelle: Wikipedia (CC-BY-SA 4.0 Lizenz)

Verhältnissymbolkarte

Punktkartogramm des gesamten Bruttoinlandsprodukts der Länder in Europa im Jahr 2018.
  • engl. ‘Proportional Symbol Map’
  • Punktsymbole unterschiedlicher Größe (Höhe, Länge, Fläche oder Volumen) werden verwendet, um quantitative statistische Werte darzustellen, die mit verschiedenen Bereichen oder Orten innerhalb der Karte verbunden sind.
  • Erfolgt die Anordnung der Punkte auf der Fläche schematisch innerhalb von (administrativen) Bezugsflächen spricht man auch von einem Punktkartogramm.

Bildquelle: Wikipedia (CC-BY-SA 4.0 Lizenz)

Punktstreukarte

  • engl. ‘Dot-Map’
  • Jeder vorhandene Datensatz wird mit einem Symbol dargestellt.
  • Bei interpolierten Daten wird ein Mittelpunkt gebildet oder es wird an der Stelle dargestellt, wo der Wert am ehesten lokalisiert ist.
  • Ziel: Erfassung des tatsächlichen Verteilungsbilds.

Isoplethenkarte (Konturkarte)

  • Besteht aus einer Menge von interpolierten Isolinien, welche aus Stichprobenpunkten von bekannten Werten generiert werden.

Beispiel von einer Schätzung über die Zahl der einheimischen Arten pro 10.000 km2

Bildquelle: Greg J. Schmidt, Misako Nishino und John Kartes. Density Gradient Map Samples Produced From BONAP’s Floristic Synthesis

Geodaten mit ggplot2 und sf

Vektordaten: Punkte, Linien, Flächen

Geodaten im Vektorformat bestehen aus drei Grundtypen:

  • Das R-Paket sf (simple features) ist der Standard für Vektordaten in R.
  • Das Prinzip: Ein ganz normaler Dataframe mit einer zusätzlichen Geometrie-Spalte (geometry).
  • → Alle dplyr-Funktionen (filter(), mutate(), left_join(), …) funktionieren wie gewohnt!

Struktur eines sf-Objekts

Frei verfügbare Ländergrenzen liefert das Paket rnaturalearth (Daten von Natural Earth, gemeinfrei):

library(sf)
library(rnaturalearth)  # zusätzlich 'rnaturalearthdata' installieren
world_sf <- ne_countries(scale = "medium", returnclass = "sf")

world_sf |>
  select(name, continent, pop_est) |>
  head(3)
Simple feature collection with 3 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 21.97891 ymin: -22.40205 xmax: 54.51113 ymax: 18.99614
Geodetic CRS:  WGS 84
      name continent  pop_est                       geometry
1 Zimbabwe    Africa 14645468 MULTIPOLYGON (((31.28789 -2...
2   Zambia    Africa 17861030 MULTIPOLYGON (((30.39609 -1...
3    Yemen      Asia 29161922 MULTIPOLYGON (((53.08564 16...

→ Die geometry-Spalte ist “sticky”: Sie bleibt auch nach select() erhalten. Im Kopf der Ausgabe stehen Geometrietyp, Ausdehnung (bounding box) und das Koordinatenreferenzsystem (CRS).

Ein sf-Objekt ansehen mit geom_sf()

  • geom_sf() erkennt die Geometrie automatisch – es braucht kein aes(x, y).
  • Mit coord_sf() kann man in einen Kartenausschnitt hineinzoomen (xlim, ylim)1.
Standard (WGS84)
ggplot(world_sf) +
  geom_sf()

Ausschnitt wählen
europe <- filter(world_sf, continent=="Europe")
ggplot(europe) + geom_sf(fill = "grey70") +
  coord_sf(xlim = c(-10, 40), ylim = c(35,70))

Weltkarte erstellen

geom_sf() kann mit anderen ggplot2-Ebenen kombiniert werden:

world_sf <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")
data(world.cities, package = 'maps')
capitals <- filter(world.cities, capital == 1)

ggplot() +
  geom_sf(data = world_sf, aes(fill = name_en)) +
  geom_point(data = capitals, mapping = aes(x = long, y = lat), colour = 'orange2') +
  scale_fill_grey() +
  guides(fill = 'none') +
  theme_minimal()

Choroplethenkarte

Eigene Daten können per left_join() an das sf-Objekt angehängt und über aes(fill = ...) dargestellt werden:

europe_wood <- europe |>
  left_join(wooded_area, by = join_by(name_en == country))

ggplot(europe_wood) +
  geom_sf(aes(fill = X2020)) +
  scale_fill_distiller(palette = "Greens",
    direction = 1, na.value = "grey90") +
  coord_sf(xlim = c(-10, 40), ylim = c(35,70)) +
  labs(fill = "Bewaldete Fläche\n2020 (1000 ha)",
    caption = "Quelle: Eurostat") +
  theme_minimal()

Die Ländernamen müssen in beiden Tabellen exakt übereinstimmen! Nicht zugeordnete Länder finden Sie mit:

anti_join(wooded_area, st_drop_geometry(europe), 
  by = join_by(country == name_en))

Kartenmaterial für die Außenalster

Für die Fallstudie stellen wir Ihnen fertige sf-Objekte bereit:

gebiete <- readRDS("data/gebiete_alster.rds") # Untersuchungsgebiete
osm <- readRDS("data/osm_alster.rds")        # OpenStreetMap-Daten (Liste)

osm ist eine Liste: Die einzelnen Ebenen erreichen Sie mit ‘$’

Objekt Geometrie Inhalt
gebiete POLYGON Erhebungsgebiete der Übungsgruppen mit den Spalten id, gruppe, uferlaenge_m und flaeche_m2
osm$water (MULTI)POLYGON Wasserflächen (Alster, Kanäle, Teiche)
osm$green (MULTI)POLYGON Grünflächen (Parks, Wiesen, Gärten, Spielplätze)
osm$buildings (MULTI)POLYGON Gebäude
osm$streets LINESTRING Straßen (Spalte highway = Straßentyp)
osm$paths LINESTRING Fuß- und Radwege (Spalte highway = Wegtyp)
osm$benches POINT Parkbänke
osm$waste_baskets POINT Mülleimer

OpenStreetMap ist eine freie Weltkarte, erstellt von Freiwilligen. Die Daten stehen unter der ODbL. Bei jeder Karte ist die Quellenangabe Pflicht: labs(caption = "© OpenStreetMap-Mitwirkende")

Die Basiskarte

alster_map <- ggplot() + # leer lassen!
  geom_sf(data = osm$green, fill = "#d8ebc4", 
    colour = NA) +
  geom_sf(data = osm$water, fill = "#aad3df", 
    colour = NA) +
  geom_sf(data = osm$buildings, fill = "grey82", 
    colour = NA) +
  geom_sf(data = osm$streets, colour = "white", 
    linewidth = 0.8) +
  geom_sf(data = osm$paths, colour = "grey60", 
    linewidth = 0.2, linetype = "dashed") +
  geom_sf(data = gebiete, fill = NA, 
    colour = "grey30") +
  coord_sf(xlim = c(9.990, 10.035), 
    ylim = c(53.555, 53.585), expand = FALSE) +
  labs(caption = "© OpenStreetMap-Mitwirkende") +
  theme_void() +
  theme(panel.background = element_rect(
    fill = "grey95", colour = NA))

alster_map
  • Die Reihenfolge der Ebenen zählt: Flächen → Linien → Punkte
  • colour = NA entfernt die Umrandung der Flächen.
  • coord_sf() legt den Kartenausschnitt fest (in Grad).
  • theme_void() entfernt Achsen und Gitterlinien.

Die Basiskarte | Mit Bänken & Mülleimern

alster_map <- ggplot() + # leer lassen!
  geom_sf(data = osm$green, fill = "#d8ebc4", 
    colour = NA) +
  geom_sf(data = osm$water, fill = "#aad3df", 
    colour = NA) +
  geom_sf(data = osm$buildings, fill = "grey82", 
    colour = NA) +
  geom_sf(data = osm$streets, colour = "white", 
    linewidth = 0.8) +
  geom_sf(data = osm$paths, colour = "grey60", 
    linewidth = 0.2, linetype = "dashed") +
  geom_sf(data = gebiete, fill = NA, 
    colour = "grey30") +
  # Bänke und Mülleimer als Punkte hinzufügen
  geom_sf(data = osm$benches, colour = "orange", 
    size = 0.5) +
  geom_sf(data = osm$waste_baskets, colour = "red", 
    size = 0.5) +
  coord_sf(xlim = c(9.990, 10.035), 
    ylim = c(53.555, 53.585), expand = FALSE) +
  labs(caption = "© OpenStreetMap-Mitwirkende") +
  theme_void() +
  theme(panel.background = element_rect(
    fill = "grey95", colour = NA))

alster_map

→ Die Karte ist als Objekt alster_map gespeichert. Ihre eigenen Daten fügen Sie später einfach mit + geom_sf(...) hinzu. Im nächsten Schritt machen wir diese Karte außerdem mit plotly interaktiv.

Eigene Messddaten in sf umwandeln

Ihre Daten liegen als Tabelle (Dataframes) mit Längen- und Breitengrad vor. Mit st_as_sf() wird daraus ein sf-Objekt: → die Spalten laengengrad und breitengrad verschwinden und wandern in die Spalte geometry.

muell |> head(3)
# A tibble: 3 × 4
  gruppe laengengrad breitengrad kategorie
  <fct>        <dbl>       <dbl> <chr>    
1 A            10.00        53.6 Glas     
2 A            10.00        53.6 Glas     
3 A            10.00        53.6 Glas     
muell_sf <- st_as_sf(muell,
  coords = c("laengengrad", "breitengrad"), # erst x, dann y!
  crs = 4326)                               # Koordinaten in Grad

muell_sf |> head(3)
Simple feature collection with 3 features and 2 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 9.996187 ymin: 53.55824 xmax: 9.997802 ymax: 53.56218
Geodetic CRS:  WGS 84
# A tibble: 3 × 3
  gruppe kategorie            geometry
  <fct>  <chr>             <POINT [°]>
1 A      Glas      (9.997802 53.56218)
2 A      Glas      (9.996187 53.55839)
3 A      Glas      (9.997046 53.55824)

Was bedeutet crs = 4326?

Das Koordinatenreferenzsystem (CRS) legt fest, wie die Zahlen zu verstehen sind. 4326 steht für WGS84: Längen- und Breitengrade in Grad, wie sie GPS-Geräte, Smartphones und what3words liefern.

Solange alle Ihre Daten in EPSG:4326 vorliegen, müssen Sie sich um das CRS nicht weiter kümmern – auch das Kartenmaterial in gebiete und osm liegen in EPSG:4326 (WGS 84) vor.

Eigene Messdaten kartieren

Den Hintergrund einmal als Objekt speichern und dann beliebig erweitern:

base_map <- ggplot() + # leer lassen!
  geom_sf(data = osm$green, fill = "#d8ebc4", 
    colour = NA) +
  geom_sf(data = osm$water, fill = "#aad3df", 
    colour = NA) +
  geom_sf(data = osm$buildings, fill = "grey82", 
    colour = NA) +
  geom_sf(data = osm$streets, colour = "white", 
    linewidth = 0.8) +
  geom_sf(data = osm$paths, colour = "grey60", 
    linewidth = 0.2, linetype = "dashed") +
  geom_sf(data = gebiete, fill = NA, 
    colour = "grey30")

muell_map <- base_map + 
  geom_sf(data = muell_sf, aes(colour = kategorie), size = 1) +
  coord_sf(xlim = c(9.990, 10.035),   
    ylim = c(53.555, 53.585), expand = FALSE) + 
  scale_colour_brewer(palette = "Set1") +
  labs(colour = "Müllkategorie",
    caption = "© OpenStreetMap-Mitwirkende") +
  theme_bw()

muell_map

Demodatensatz

Karte aufteilen

muell_map +
  facet_wrap(~ kategorie, nrow = 2) +
  guides(
    colour = "none", 
    x = guide_axis(angle = 45)
  )
  • → Die Hintergrund-Ebenen haben keine Spalte kategorie und werden daher in jeder Facette gezeichnet.

Labels, Maßstab & Nordpfeil

Labels können mit geom_sf_label() hinzugefügt werden. Das Paket ggspatial ergänzt Kartenelemente:

gebiete_labels <- gebiete |>
  group_by(gruppe) |>
  summarise() # vereinigt die Geometrien je Gruppe

muell_map +
  # Legende
  geom_sf_label(data = gebiete_labels, 
    aes(label = gruppe),
    fun.geometry = sf::st_centroid, # Labels zentrieren
    size = 3, linewidth = 0, alpha = 0.7) +
  labs(x = NULL, y = NULL) +
  # Maßstab
  ggspatial::annotation_scale(location = "br",
    height = unit(0.1, "cm"),     # Dicke der Leiste 
    line_width = 0.5,             # Randlinie
    text_cex = 0.7) +             # Schriftgröße
  # Nordpfeil
  ggspatial::annotation_north_arrow(location = "tr",
    height = unit(0.75, "cm"), width = unit(0.5, "cm"),
    style = ggspatial::north_arrow_minimal())
  • location: Position als Kombination aus bottom/top und left/right
  • Die Maßstabsleiste rechnet die Grad-Koordinaten automatisch in Meter um.

Karten in Ihrer Fallstudie

Checkliste für Ihre Karte

  • Ausschnitt anpassen: Die Grenzen in coord_sf() so wählen, dass Ihr Gebiet gut sichtbar ist. Koordinaten finden Sie z.B. per Rechtsklick auf openstreetmap.org → Adresse anzeigen.
  • Viele Punkte? Mit size und alpha (Transparenz) verhindern Sie, dass sich Punkte gegenseitig verdecken.
  • Legende und Beschriftung auf Deutsch und mit Einheiten (labs()).
  • Quellenangabe © OpenStreetMap-Mitwirkende nicht vergessen.
  • Maßstab und Nordpfeil gehören zu jeder guten Karte.

→ Eine interaktive Variante mit leaflet lernen Sie im nächsten Abschnitt kennen. Diese funktioniert allerdings nur im HTML-Output – für Ihren Bericht brauchen Sie die statische Karte (Screenshot!).

Hinweis: Paketversionen

Unterschiedliche Paketversionen

Auf dem Server laufen teils noch ältere Paketversionen. Dann können folgende Unterschiede auftreten:

Ältere Versionen (Server) Neuere Versionen
geom_sf(size = 0.3) für Linienstärke geom_sf(linewidth = 0.3) (ab ggplot2 3.4)
borders() annotation_borders() (ab ggplot2 4.0)

Ihre installierte Version prüfen Sie mit packageVersion("ggplot2").

  • In VL10 haben wir eine Karte mit map_data(), geom_polygon() und coord_map() erstellt. Dieser Weg eignet sich gut für schnelle Übersichtskarten mit Ländergrenzen. Für eigene Geodaten ist sf mit geom_sf() und coord_sf() der heutige Standard – Sie finden den älteren Weg aber noch häufig in Skripten und Foren.
  • sf benötigt Systembibliotheken (GDAL, GEOS, PROJ). Auf dem Server sind diese installiert; bei der Installation auf dem eigenen Rechner (v.a. Linux) kann es Hürden geben.

Interaktive Grafiken

HTML-Widgets

Mithilfe des Frameworks htmlwidgets gibt es R-Schnittstellen für JavaScript (JS) Visualisierungsbibliotheken, z.B.:

  • Weitere: dygraphs für Zeitreihen (Link), highcharter für die Highcharts-Bibliothek (Link), DT für interaktive Tabellen (Link)

→ HTML-Widgets funktionieren wie R-Plots, erzeugen aber interaktive Webgrafiken. Sie laufen in der Konsole, in Quarto-Dokumenten und in Shiny-Apps – und alle arbeiten mit dem Pipe-Operator.

HTML-Widgets | Beispiele

plotly

leaflet

Von ggplot2 zu plotly | 1

  • Mit ggplotly() können ggplot2-Grafiken ganz einfach in interaktive Diagramme umgewandelt werden!
gg_bill <- penguins |> 
  ggplot(aes(
    x = bill_length_mm, 
    y = body_mass_g, 
    color = species)
  ) +
  geom_point()
# Umwandlung zu plotly Objekt
ggplotly(gg_bill) 

Von ggplot2 zu plotly | 2

Die Alsterkarte

ggplotly(muell_map)

plotly | Menüleiste

Features

  • Download als PNG Datei
  • Zoomen
  • Legendenelemente auswählen
  • Hovering um Werte zu erhalten
  • ‘Home’ Schaltfläche
  • Schwenken
  • Automatische Skalierung
  • Reset
  • Vergleich von Datenpunkten beim Hovern


Anpassung

Mit der config() Funktion:

p_bill <- ggplotly(gg_bill)
config(p_bill,
  # Menüleiste komplett entfernen:
  displayModeBar = FALSE,
  # oder nur einzelne Elemente:
  displaylogo = FALSE,
  modeBarButtonsToRemove = c(
    'zoomIn2d', 'zoomOut2d'))

Animationen mit plotly

  • Für Animationen muss das frame Aesthetic definiert werden!
library(gapminder)

gg <- gapminder |> 
  ggplot(aes(
    x = gdpPercap, 
    y = lifeExp,
    color = continent, 
    size = pop, 
    frame = year)
  ) + 
  geom_point() + 
  scale_x_log10()
ggplotly(gg)

plotly | Mehr Möglichkeiten

  • Die Möglichkeiten mit ggplot2 und der Konvertierungsfunktion ggplotly() sind begrenzt.
  • Mehr Optionen gibt es bei der Verwendung von plotly’s eigener Syntax:
Code
library(reshape2)
library(tidyverse)
library(tidymodels)
library(plotly)
library(kernlab)
library(pracma) # Für meshgrid()

mesh_size <- .02
margin <- 0
X <- iris |> select(Sepal.Width, Sepal.Length)
y <- iris |> select(Petal.Width)

model <- svm_rbf(cost = 1.0) |> 
  set_engine("kernlab") |> 
  set_mode("regression") |> 
  fit(Petal.Width ~ Sepal.Width + Sepal.Length, data = iris)

x_min <- min(X$Sepal.Width) - margin
x_max <- max(X$Sepal.Width) - margin
y_min <- min(X$Sepal.Length) - margin
y_max <- max(X$Sepal.Length) - margin
xrange <- seq(x_min, x_max, mesh_size)
yrange <- seq(y_min, y_max, mesh_size)
xy <- meshgrid(x = xrange, y = yrange)
xx <- xy$X
yy <- xy$Y
dim_val <- dim(xx)
xx1 <- matrix(xx, length(xx), 1)
yy1 <- matrix(yy, length(yy), 1)
final <- cbind(xx1, yy1)
pred <- model |>
  predict(final)

pred <- pred$.pred
pred <- matrix(pred, dim_val[1], dim_val[2])

fig <- plot_ly(iris, x = ~Sepal.Width, y = ~Sepal.Length, z = ~Petal.Width, height = 700, width = 800) |> 
  add_markers(size = 5) |> 
  add_surface(x=xrange, y=yrange, z=pred, alpha = 0.65, type = 'mesh3d', name = 'pred_surface')
fig

plotly | Export als HTML- oder Bilddatei

Zum Speichern gibt es bei plotly 3 Möglichkeiten:

  1. Die GUI von RStudio/Posit nutzen.
  2. Die Download-Schaltfläche von Plotlys Menüleiste verwenden.

  1. Mit der saveWidget() Funktion im Paket htmlwidgets das Diagramm als HTML-Datei speichern und mit webshot() aus dem webshot2 Paket diese zu PNG umwandeln:
# Speichern im HTML-Format
htmlwidgets::saveWidget(widget = p_bill, file = "plotly-Diagramm.html")

# Umwandlung von HTML zu PNG, JPG,..
webshot2::webshot(url = "plotly-Diagramm.html", file = "plotly-Diagramm.png",
  vwidth = 600, vheight = 480)

leaflet | Standardweltkarte

→ leaflet() und addTiles()

library(leaflet)
m <- leaflet() |>   # erstellt das Grundgerüst (ähnlich wie ggplot())
  addTiles()        # hinzufügen einer Karte -> Standard: OpenStreetMap
m

leaflet | Zoomen

→ setView()

Schwache Vergrößerung: zoom = 5
m |> setView(zoom = 5,
  lng = 9.97874, lat = 53.56745) 
Starke Vergrößerung: zoom = 20
m |> setView(zoom = 20,
  lng = 9.97874, lat = 53.56745) 

leaflet | Weitere Karten

→ addProviderTiles()

Esri.WorldPhysical
leaflet() |> 
  setView(lng = 10, lat = 53, zoom = 4) |> 
  addProviderTiles(providers$Esri.WorldPhysical)
Esri.WorldImagery mit OpenRailwayMap
leaflet() |>
  setView(lng = 11, lat = 55, zoom = 8) |>
  addProviderTiles(providers$Esri.WorldImagery) |>
  addProviderTiles(providers$OpenRailwayMap)

Eine Demo aller Kartenanbieter: leaflet-extras.github.io/leaflet-providers/preview (Namen auch über names(providers))

leaflet | Hinzufügen von Elementen

Rechtecke und Markierungspunkte

→ addMarkers(), addCircleMarkers() und addRectangles()

Code
long <- 9.9789
lat <- 53.5675
leaflet() |>
  addTiles() |>
  setView(lng = long, lat = lat, zoom = 18) |>
  # Rechteck:
  addRectangles(
    lng1 = 9.978, lat1 = 53.5671,
    lng2 = 9.9795, lat2 = 53.5679,
    fillColor = "transparent") |>
  # sog. Icon Markers:
  addMarkers(lng = long, lat = lat,
    popup = "Eingang des Instituts für Zell- und Systembiologie der Tiere (IZS)",
    label = "IZS") |>
  # Kreismarkierung:
  addCircleMarkers(lng = 9.97925, lat = 53.56735,
    popup = "Gr. Hörsaal der Zoologie", label = "Unser Standort",
    color = "red", radius = 35, stroke = TRUE, opacity = 0.5,
    weight = 3, fill = TRUE, fillColor = "red", fillOpacity = 0.2)

leaflet | sf-Objekte darstellen

leaflet versteht sf-Objekte direkt – Variablen werden wie bei plotly mit ~ angesprochen:

pal <- colorFactor(palette = "Set1",
  domain = muell_sf$kategorie)

leaflet(muell_sf) |>
  addTiles()  |> 
  addCircleMarkers(
    radius = 5, 
    stroke = FALSE,
    fillOpacity = 0.8, 
    color = ~pal(kategorie),
    label = ~kategorie  # beim Hovern
  ) |>
  addLegend(
    title = "Müllkategorie", pal = pal, 
    values = ~kategorie,
    position = "topleft"
)

leaflet erwartet Koordinaten in Grad (EPSG:4326). Liegen die Daten in einem anderen CRS vor, vorher st_transform(daten, crs = 4326) anwenden!

leaflet | Export als HTML- oder Bilddatei

Zum Speichern gibt es 2 Möglichkeiten:

  1. Die GUI von RStudio/Posit nutzen.

  1. Mit der saveWidget() und webshot() Funktion wie bei plotly:
m <- leaflet(muell_sf) |> addTiles() |> addCircleMarkers()
# Speichern im HTML-Format
htmlwidgets::saveWidget(widget = m, file = "leaflet-Karte.html")
# Umwandlung von HTML zu PNG, JPG,..
webshot2::webshot(url = "leaflet-Karte.html", file = "leaflet-Karte.png",
  vwidth = 805, vheight = 480)

Your turn …

Kombinieren & (interaktive) Karten

Übungen

Optionale swirl-Lektionen zur Vertiefung

Kurs DSB-04-Datenvisualisierung mit ggplot2

  • L13-Plots kombinieren
  • L14-Karten erstellen mit ggplot2
  • L15-Umwandlung zur interaktiven plotly_Grafik
  • L16-plotly Objekte besser verstehen

Übungsaufgaben Woche 12

Alle Aufgaben der Übungswoche finden Sie im Handbuch:

  • die zu bearbeitenden Übungsskripte
  • die (optionalen) swirl-Lektionen und
  • den aktuellen Stand der Fallstudie.
  • Die Übungsskripte und Daten liegen in Ihrem R-Projektordner DS1-R-Uebungen (Unterordner uebungsskripte bzw. data).
  • Öffnen Sie immer zuerst die Projektdatei DS1-R-Uebungen.Rproj, dann stimmen alle Dateipfade.

Wie fühlen Sie sich jetzt…?

Total konfus?


Bei weiteren Fragen: saskia.otto(at)uni-hamburg.de

Creative Commons License
Diese Arbeit is lizenziert unter einer Creative Commons Attribution-ShareAlike 4.0 International License mit Ausnahme der entliehenen und mit Quellenangabe versehenen Abbildungen.