Data Science 1 - Programmieren & Visualisieren
Saskia Otto
Universität Hamburg, IMF
Wintersemester 2022/2023
Darstellung des räumlichen Musters der Meeresoberflächentemperatur (im Engl. ‘sea surface temperature’ bzw. SST genannt) in der Ostsee (im Engl. ‘Baltic Sea’) im Sommer 2015:
# library(ggplot2) # oder: library(tidyverse)
p1 <- ggplot(sst_sum, aes(long, lat)) +
geom_point(aes(colour = temp, shape = month))
world <- map_data("world")
worldmap <- ggplot(world, aes(x = long, y = lat)) +
geom_polygon(aes(group = group), fill = "ivory3", colour = "black")
baltic <- worldmap + coord_map("ortho", xlim = c(10, 30), ylim = c(54,66))
p2 <- baltic +
geom_point(data = sst_sum,
aes(x = long, y = lat, colour = temp), size = 1) +
scale_colour_gradient(low = "white", high = "red") +
facet_wrap(~month) +
labs(x = "Longitude", y = "Latitude",
title = "Thermal pattern in the Baltic Sea",
subtitle = "SST in the summer months of 2015") +
guides(colour = guide_colourbar(title = "SST (in °C)")) +
ggthemes::theme_base(base_size = 11) +
theme(
legend.position = "bottom",
legend.title.align = 1,
legend.title = element_text(colour = "red", angle = 0),
panel.background = element_rect(fill = "lightblue1")
)
gridExtra::grid.arrange(p1, p2, nrow=1)
Datensatz ist im Paket ‘marinedata’ enthalten:
# Laden des Datensatzes zur Ostsee (Baltic Sea) Hydrografie 2015
data(bshydro15, package = "marinedata")
str(bshydro15)
tibble [61,149 × 15] (S3: tbl_df/tbl/data.frame)
$ cruise : chr [1:61149] "????" "????" "????" "????" ...
$ station : chr [1:61149] "0002" "0002" "0002" "0002" ...
$ lat : num [1:61149] 55.1 55.1 55.1 55.1 55.1 ...
$ long : num [1:61149] 10.8 10.8 10.8 10.8 10.8 ...
$ ices_sd : Factor w/ 13 levels "IIIa","22","23",..: 2 2 2 2 2 2 2 2 2 2 ...
$ sampling_id: int [1:61149] 1 1 1 1 1 1 2 2 2 2 ...
$ date_time : POSIXct[1:61149], format: "2015-01-05 08:17:00" "2015-01-05 08:17:00" ...
$ year : int [1:61149] 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 ...
$ month : Factor w/ 12 levels "Jan","Feb","Mar",..: 1 1 1 1 1 1 1 1 1 1 ...
$ day : int [1:61149] 5 5 5 5 5 5 5 5 5 5 ...
$ bot_depth : int [1:61149] 12 12 12 12 12 12 10 10 10 10 ...
$ pres : num [1:61149] 0.2 1 5 10 11.3 11.9 0.2 1 5 8.9 ...
$ temp : num [1:61149] 4.9 4.89 4.89 4.91 4.91 4.95 4.28 4.4 4.5 5.28 ...
$ psal : num [1:61149] 24 24 24 24.1 24.1 ...
$ doxy : num [1:61149] 5.34 5.34 5.34 5.4 5.4 5.4 5.29 5.29 5.19 5 ...
Schrittweise Berechnung der gemittelten SST (0-5m) pro Sampling in den Sommermonaten:
sst_sum <- bshydro15 |>
# Filtern der Sommermonate und Oberflächenmessungen (0-5m)
filter(pres <= 5, month %in% c("May", "Jun", "Jul", "Aug")) |>
# Gruppierung nach Variablen die Sampling definieren
group_by(station, lat, long, date_time, month, day) |>
# Bildung des Temperaturmittelwerts über die 5m
summarise(temp = mean(temp, na.rm = TRUE)) |>
ungroup() |>
# Hinzufügen des Probezeitraums
mutate(
hour = lubridate::hour(date_time), # Extrahiert die Stunde
sampling = case_when( # Bildet Kategorien basierend auf den Stunden
hour >= 6 & hour < 21 ~ "day",
TRUE ~ "night")
)
ggplot()
)aes()
)colours()
.Für einige Grundelemente kann man 2 Farbattribute wählen: die Konturfarbe (colour) und die Füllfarbe (fill)
Die voreingestellte Form hat die Nummer 19.
shapes <- data.frame(
shape = 24:0,
x = rep(5:1, 5),
y = rep(1:5, each = 5)
)
ggplot(shapes, aes(x, y)) +
geom_point(aes(shape = shape),
size = 8, fill = "red") +
geom_text(aes(label = shape),
hjust = 0, nudge_x = 0.15) +
scale_shape_identity() +
expand_limits(x = 4.1) +
scale_x_continuous(NULL,
breaks = NULL) +
scale_y_continuous(NULL,
breaks = NULL)
… können spezifiziert werden mit einem Namen oder einer Zahl von 0-6:
labels <- rev(c("blank = 0",
"solid = 1", "dashed = 2",
"dotted = 3", "dotdash = 4",
"longdash = 5","twodash = 6")
)
lty <- 6:0
linetypes <- data.frame(
y = seq_along(lty),
lty = lty
)
ggplot(linetypes, aes(0, y)) +
geom_segment(aes(xend = 5,
yend = y, linetype = lty)) +
scale_linetype_identity() +
geom_text(aes(label = labels),
hjust = 0, nudge_y = 0.2,
size = 6) +
scale_x_continuous(NULL,
breaks = NULL) +
scale_y_continuous(NULL,
breaks = NULL)
df <- data.frame(x = 1, y = 3:1,
family = c("sans", "serif", "mono"),
fontface = c("plain", "italic", "bold"))
df$label <- paste0("'", df$family,
"' und '", df$fontface, "'")
ggplot(df, aes(x, y)) + ylim(0,4) +
geom_text(aes(label = label,
family = family, fontface = fontface),
size = 6) +
theme(
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank(),
plot.background = element_blank()
)
Zur horizontalen (hjust) und vertikalen (vjust) Ausrichtung des Bezugspunkt zum Label (!)
just <- expand.grid(hjust = c(0,0.5,1),
vjust = c(0, 0.5, 1))
hjust_txt <- rep(c("left", "center",
"right"), 3)
vjust_txt <- rep(c("bottom", "middle",
"top"), each = 3)
just$label <- paste0(hjust_txt, "/",
vjust_txt)
ggplot(just, aes(hjust, vjust)) +
geom_point(colour = "grey70",
size = 5) +
geom_text(aes(label = label,
hjust = hjust, vjust = vjust),
size = 5)
00:30
Es soll ein sog. Blasenplot (‘bubble plot’) erstellt werden, sprich ein Streudiagramm bei dem die Größe der Punkte abhängig ist von einer dritten, quantitativen Variable (‘z’).
aes()
):
scale_x_continuous()
scale_x_log10()
scale_x_reverse()
scale_x_sqrt()
xlim()
, ylim()
, lims()
(tausche x einfach gegen y)
lassen sich die Skalenfunktionen
scale_XXX_manual()
scale_XXX_identity()
scale_XXX_discrete()
scale_XXX_continuous()
scale_XXX_binned()
verwenden.
Hier ein Beispiel, wo scale_x_reverse()
und scale_x_continuous()
in Kombination mit sec_axis()
für eine Sekundärachse sehr praktisch sind:
bshydro15 |>
filter(station == "0508", day == 5,
month == "Aug") |>
ggplot(aes(y = pres)) +
geom_path(aes(x = temp), col = "red") +
geom_path(aes(x = psal), col = "blue") +
# Variable der Sekundärachse anpassen:
geom_path(aes(x = doxy*2), col="green") +
scale_y_reverse() +
scale_x_continuous(
sec.axis = sec_axis(
~./2, # = Primärachse (.) durch 2
name="doxy"))
Die Voreinstellung von ‘ggplot2’ bei Variablen vom Typ character oder factor ist (in Abhängigkeit davon wieviele Farben benötigt werden):
Die Voreinstellung von ‘ggplot2’ bei Variablen vom Datentyp integer oder double ist:
ggplot2 erkennt automatisch, ob Variablen qualitativ oder quantitativ sind:
→ scale_colour_manual()
→ scale_colour_grey()
Die ‘brewer’ Palette in scale_colour_brewer()
bietet schöne Farbschemata von ‘ColorBrewer’, die speziell für Karten gefertigt wurde: http://colorbrewer2.org
Mit folgendem Befehl wird eine Liste jeder ‘brewer’ Palette aufgerufen:
→ scale_colour_brewer()
scale_colour_gradient()
ist die voreingestellte Farbskala. Sie erzeugt einen Gradienten von niedrig zu hoch (siehe rechten Plot).scale_colour_gradient2()
erzeugt einen auseinanderlaufen Farbverlauf mit 3 Farben (niedrig//mittel/hoch) und ist besonders zum Setzen von Kontrasten geeignet.scale_colour_gradientn()
erzeugt einen Gradienten mit n Farben.→ scale_colour_gradient()
→ scale_colour_gradient2()
→ scale_shape_manual()
bei qualitativen Variablen
→ scale_shape_identity()
scale_shape_identity()
hinzugefügt wird (ansonsten gibt es eine Fehlermeldung).Das Größenattribut wird am häufigsten für Punkte und Text verwendet. Variablen-spezifische Zuweisungen lassen sich modifizieren mit:
scale_size()
→ skaliert Flächescale_size_area()
→ stellt sicher, dass ein Wert von 0 mit einer Größe von 0 abgebildet wirdscale_size_binned()
/ scale_size_binned_area()
→ gebinnte VersionDie Verwendung transparenter Farben (mit dem ‘alpha’ Attribut) zeigt sehr gut überlappende Punkte!
Es gibt Skalen für jedes Attribut, das von ‘ggplot2’ verwendet wird. Um eine komplette Liste mit Beispielen zu sehen siehe https://ggplot2.tidyverse.org/reference/#scales
Bildschirmfoto der Website (aufgenommen Jan. 2022)
00:30
Beim sog. Blasenplot (‘bubble plot’) soll die Größenskala angepasst werden. Und zwar sollen die Größenstufen in 1er-Schritten von 2 bis 10 gehen.
→ facet_wrap()
, facet_grid()
00:30
Ein Streudiagramm soll entsprechend einer kategorialen Variable (‘z’) in Teildiagramme (‘facets’) aufgeteilt werden. Diese Teildiagramme sollen dabei in einer Spalte angeordnet werden.
coord_cartesian()
coord_fixed()
coord_flip()
coord_trans()
coord_polar()
coord_sf()
coord_map()()
, coord_quickmap()
Das Setzen der Achsengrenzen im Koordinatensystems verändert nicht die Daten, sondern ist wirklich nur als Zoomen zu betrachten. Die Glättungskurve hat sich für diesen Ausschnitt nicht verändert.
Das Setzen der Achsengrenzen auf der Skalenebene wandelt alle Werte außerhalb des Bereichs in NA um. Entsprechend sieht die Glättungskurve für diesen Bereich anders aus, als im größeren Ausschnitt!
coord_polar()
Im Buch ‘Grammar of Graphics’ wird ein Tortendiagram als ein gestapeltes Säulendiagramm mit polaren Koordinaten definiert:
Was jetzt nötig ist, ist das Aufräumen einiger Elemente… (siehe nächstes Kapitel)!
coord_map()
coord_map()
projiziert einen Ausschnitt der annähernd kugelförmigen Erde auf eine flache 2D-Ebene mit Hilfe einer Projektion, die durch das Paket ‘mapproj’ definiert ist.
00:30
xlab()
, ylab()
ggtitle()
labs()
p1 <- ggplot(sst_sum, aes(long, lat)) + geom_point(aes(colour = temp, shape = month)) +
scale_colour_gradient(low = "white", high = "red") +
labs(x = "Longitude", y = "Latitude", colour = "SST", shape = "Month", # alle Aesthetics
title = "Thermal patterns in the Baltic Sea",
subtitle = "SST (0-5m) in summer 2015")
p1
Es gibt verschiedene Möglichkeiten, die Legende für Variablen-spezifische Attribute anzupassen:
guides()
→ Für jedes Attribut kann mittels Helferfunktion die Legende angepasst werden.guide_none()
guide_axis()
guide_colourbar()
guide_coloursteps
guide_legend()
guide_bins()
theme_XXX()
Funktionen genutzt werden können.theme()
Funktion verändert werden.theme_gray()
theme_dark()
theme_bw()
theme_linedraw()
theme_light()
theme_minimal()
theme_test()
theme_classic()
theme_void()
dp <- p2 + guides(colour = "none", shape = "none")
t1 <- dp + theme_dark() + ggtitle("theme_dark")
t2 <- dp + theme_gray() + ggtitle("theme_gray")
t3 <- dp + theme_bw() + ggtitle("theme_bw")
t4 <- dp + theme_linedraw() + ggtitle("theme_linedraw")
t5 <- dp + theme_light() + ggtitle("theme_light")
t6 <- dp + theme_minimal() + ggtitle("theme_minimal")
t7 <- dp + theme_test() + ggtitle("theme_test")
t8 <- dp + theme_classic() + ggtitle("theme_classic")
t9 <- ggplot() + theme_void() # leerer Plot
t10 <- dp + theme_void() + ggtitle("theme_void")
gridExtra::grid.arrange(grobs = list(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10), nrow = 2)
Damit unser Plot auch wirklich aussieht wie ein typisches Tortendiagramm, nutzen wir die minimalistische Layoutvorlagen, die ggplot2 anbietet: theme_void()
install.packages('ggthemes', dependencies = TRUE)
devtools::install_github('ricardo-bion/ggtech', dependencies = TRUE)
library(ggthemes)
gp <- p2 + guides(colour = "none", shape = "none")
t1 <- gp + theme_excel() + ggtitle("theme_excel")
t2 <- gp + theme_economist() + ggtitle("theme_economist")
t3 <- gp + theme_solarized() + ggtitle("theme_solarized")
t4 <- gp + theme_tufte() + ggtitle("theme_tufte")
t5 <- gp + theme_gdocs() + ggtitle("theme_gdocs")
t6 <- gp + theme_wsj() + ggtitle("theme_wsj")
t7 <- gp + theme_base() + ggtitle("theme_base")
t8 <- gp + theme_fivethirtyeight() + ggtitle("theme_fivethirtyeight")
gridExtra::grid.arrange(grobs = list(t1,t2,t3,t4,t5,t6,t7,t8), nrow = 2)
→ theme()
In der Hilfe bzw. Funktionsdokumentation finden Sie eine Übersicht über alle Komponenten, die Sie in der Funktion anpassen können:
01:00
Wie kann die von ggplot2 automatisch erstellte Legende im Blasenplot (‘bubble plot’) wieder entfernt werden?
→ Schauen wir uns den Code im Detail an..
Der Code
library(ggplot2) # oder: library(tidyverse)
world <- map_data("world")
worldmap <- ggplot(world, aes(x = long, y = lat)) +
geom_polygon(aes(group = group),
fill = "ivory3", colour = "black")
baltic <- worldmap + coord_map("ortho",
xlim = c(10, 30), ylim = c(54,66))
p2 <- baltic +
geom_point(data = sst_sum,
aes(x = long, y = lat, colour = temp), size = 1) +
scale_colour_gradient(low = "white", high = "red") +
facet_wrap(~month) +
labs(x = "Longitude", y = "Latitude",
title = "Thermal pattern in the Baltic Sea",
subtitle = "SST in the summer months of 2015") +
guides(colour = guide_colourbar(title = "SST (in °C)")) +
ggthemes::theme_base() +
theme(
legend.position = "bottom",
legend.title.align = 1,
legend.title=element_text(colour ="red", angle = 0),
panel.background = element_rect(fill = "lightblue1")
)
p2
Dann testen Sie doch Ihr Wissen in den folgenden Quizfragen..
ggplot(daphnia,
aes(x = treatment, y = offspring)) +
geom_boxplot(aes(fill = treatment)) +
scale_fill_manual(name = 'Treatment',
values = c('yellow', 'orange')) +
facet_grid(pop ~ .) +
coord_flip() +
ggtitle(label = 'Populations differences') +
ylab('Total number of offsprings') +
xlab('Treatment') +
theme_bw()
Bei weiteren Fragen: saskia.otto(at)uni-hamburg.de
Diese Arbeit is lizenziert unter einer Creative Commons Attribution-ShareAlike 4.0 International License mit Ausnahme der entliehenen und mit Quellenangabe versehenen Abbildungen.
Kurswebseite: Data Science 1