Lösungen vorhanden

Rmd

Hier wird vor allem der Befehl ggplot() aus der `library(“ggplot2”) dargestellt.

ggplot() Konzeptuelles

ggplot() dient dem Erstellen von zweidimensionalen Grafiken. Es ist nicht geeignet für 3d-Grafiken.

In vielen Grafiken stellen wir auf der Y-Achse eine Reaktionsvariable (AV) dar. Auf der X-Achse findet sich entweder eine stetige Variable (intervallskaliert oder rangskaliert) oder eine nominalskalierte Variable (Gruppierungsvariable). Bei stetigen Variablen handelt es sich oft um Covariaten, häufig auch um zeitliche Verläufe (Zeitachse). Insbesondere für die Visualisierung von Verläufen oder Entwicklungen sollten die Daten im Long-Format vorliegen: Unit long_wide Bei nominalskalierten Variablen geht es häufig um Gruppierungen der Beobachtungen, teils auch hinsichtlich mehrerer Gruppierungsvariablen. Die Zuordnung von Variablen zu Achsen geschieht in den Aestetics (aes()).

Mit den Befehlen geom_...() legen wir die Art der graphischen Darstellung fest (Punktwolke, Balken- oder Liniengraph).

ggplot-Grafiken sind modular aufgebaut, sie implementieren das Konzept von Layers (Schichten, Folien). Wir können eine Vielzahl von Grafikarten, Darstellungsarten und sogar mehrere verschiedene Datenobjekte als Datenquelle in einer einzigen Endgrafik visualisieren.

Häufig müssen die Daten für die Grafik noch aggregiert werden. D. h. aus den Rohdaten müssen die darzustellenden Werte erst berechnet werden. ggplot_aggregating

Manchmal aber haben wir bereits Ergebnisse für aggregierte Werte vorliegen, die visualisiert werden sollen. Ein Aggregieren ist dann nicht notwendig. ggplot_fix

Sehr mächtig wird ggplot() durch das Prinzip der Vererbung. Mit dem Befehl ggplot() wird ein Grafikobjekt erzeugt. Grundeigenschaften dieses Grafikobjekts legen wir sinnvollerweise hier an. Meist ist es sinnvoll, hier beispielsweise die (Haupt-) Datenquelle festzulegen und welche Variablen die Koordinaten bilden. Schließlich kann man hier auch bereits Eigenschaften (aesthetics) der Grafik festlegen, die für alle Unterbefehle (Layers) gelten.

Nicht spezifisch für ggplot(), aber in diesem Kontext besonders wichtig: Wenn ein Rmd gerendert (knited) wird und das Ausgabeformat HTML ist, wird ein einziges HTML-File erzeugt, das auch die Grafiken enthält (base64 conversion: <img src="data:image/png;base64,iVBOR...).

Jede ggplot2-Grafik hat drei Kernkomponenten:

  • Daten (Dataframe bzw. Tibble)
  • Ein Set von Verknüpfungen zwischen Variablen in den Daten und visuellen Eigenschaften (aesthetics)
  • geom, ein geometrisches Layer-Objekt das beschreibt, wie jeder Datenpunkt gerendert (aufbereitet, wiedergegeben) wird.

Anatomie, Layers

Konzept von Hadley Wickham

Normalerweise wird ein Layer nicht explizit aufgerufen, sondern wird über geom...() implizit erzeugt. Fünf Komponenten eines Layer: data, the aesthetic mappings, the geom, stat, and position adjustments. Jedes Layer-Objekt kann auf eigene Daten (Dataframe) zurückgreifen, kann aber auch die Daten des ggplot-Objekts erben.

Grafikobjekt erzeugen. Layers hinzufügen. Ausgeben auf Bildschirm bzw. in Datei speichern. Layer werden mit dem ‘+’ Operator an das Grafikobjekt angehängt. Das ‘+’ zum Hinzfügen von Layers kann bei mehrzeiligen Grafikbefehlen am Ende einer Zeile stehen, nicht jedoch am Anfang.

geom() und aes()

Eine knappe Einführung/ quick reference in die Struktur (anatomy) von ggplot2 Grafiken:

Eine Slideshow zu ggplot2 von Istvan Zahn Slideshow

Gometric objects geom_...()

Definieren, welche Art von geometrischem Objekt auf den Layer ausgegeben wird. Layer wird implizit erzeugt.

Entweder über den Befehl layer() oder über Spezialbefehle, die einen bestimmten Typ von Layer implizieren. layer(geom="point") ist äquivalent zu geom_point() Ein paar geom...()

  geom_bar
  geom_point
  geom_line
  geom_smooth
  geom_histogram
  geom_boxpolot
  geom_text
  geom_density
  geom_errorbar
  geom_hline, geom_vline

Welche geoms gibt es?

require("ggplot2")
## Lade nötiges Paket: ggplot2
# get a list of all currently available geoms
geoms <- help.search("geom_", package="ggplot2")
# show name and title of the first 5 geoms
geoms$matches[1:5, 1:2]
##         Topic                                               Title
## 1 geom_abline Reference lines: horizontal, vertical, and diagonal
## 2 geom_abline Reference lines: horizontal, vertical, and diagonal
## 3 geom_abline Reference lines: horizontal, vertical, and diagonal
## 4    geom_bar                                          Bar charts
## 5    geom_bar                                          Bar charts
# which arguments can be used in a specific geom, here for geom_boxplot
args(geom_boxplot)
## function (mapping = NULL, data = NULL, stat = "boxplot", position = "dodge2", 
##     ..., outlier.colour = NULL, outlier.color = NULL, outlier.fill = NULL, 
##     outlier.shape = 19, outlier.size = 1.5, outlier.stroke = 0.5, 
##     outlier.alpha = NULL, notch = FALSE, notchwidth = 0.5, varwidth = FALSE, 
##     na.rm = FALSE, orientation = NA, show.legend = NA, inherit.aes = TRUE) 
## NULL

Aesthetics aes()

Ein Set von Verknüpfungen zwischen Variablen in den Daten und visuellen Eigenschaften (aesthetics) Gestaltungsmerkmale, die global gesetzt und ggf lokal überschrieben werden können, oder die nur lokal definiert werden. geom definiert, welche aestetics (subset) erlaubt sind. z. B.

postition linetype size shape colour alpha

aes können global oder lokal gelten

stats

stats dienen dem Aggregieren der Daten für die graphische Darstellung. Dieser Aspekt wird näher dargestellt in ggplot_aggregateing

stats können von geoms benutzt werden oder generieren auch selbstständig grafische Elemente. Sie dienen dazu, die für die Darstellung notwendigen Parameter aus (Roh-)Daten zu erstellen.

Viele geom()s müssen die Rohdaten transformieren. Dazu dient stat().

# find all versions of stats
stats <- help.search("stat_", package="ggplot2")
# get the first 5, their name and title
stats$matches[1:5, 1:2]
##          Topic                                           Title
## 1     geom_bar                                      Bar charts
## 2  geom_bin_2d                        Heatmap of 2d bin counts
## 3  geom_bin_2d                        Heatmap of 2d bin counts
## 4 geom_boxplot A box and whiskers plot (in the style of Tukey)
## 5 geom_contour                     2D contours of a 3D surface

Um zu verstehen, was stats tun, kann man sie außerhalb des ggplot-Kontexts laufen lassen und sich die Ergebnisse ansehen

# some values in a vector
vv <- c(100, 111, 112, 104,  98,  87,  95,  90, 
         90,  97, 102,  95,  88,  79,  82,  83)
# a factor-like vector
gg <- c(  1,   1,   1,   1,   1,   1,   1,   1,
          2,   2,   2,   2,   2,   2,   2,   2)
# tapply(data, group, function)
# tapply applies a function to eac subgroup defined by group to the data of that group

require(Hmisc)
## Lade nötiges Paket: Hmisc
## Lade nötiges Paket: lattice
## Lade nötiges Paket: survival
## Lade nötiges Paket: Formula
## 
## Attache Paket: 'Hmisc'
## Die folgenden Objekte sind maskiert von 'package:base':
## 
##     format.pval, units
# mean_cl_normal is a stat used by errorbar
tapply(vv, gg, mean_cl_normal)
## $`1`
##        y   ymin    ymax
## 1 99.625 92.029 107.221
## 
## $`2`
##      y     ymin     ymax
## 1 89.5 82.76719 96.23281
# boxplot is a stat used by boxplot
tapply(vv, gg, boxplot)

## $`1`
## $`1`$stats
##       [,1]
## [1,]  87.0
## [2,]  92.5
## [3,]  99.0
## [4,] 107.5
## [5,] 112.0
## 
## $`1`$n
## [1] 8
## 
## $`1`$conf
##           [,1]
## [1,]  90.62078
## [2,] 107.37922
## 
## $`1`$out
## numeric(0)
## 
## $`1`$group
## numeric(0)
## 
## $`1`$names
## [1] "1"
## 
## 
## $`2`
## $`2`$stats
##       [,1]
## [1,]  79.0
## [2,]  82.5
## [3,]  89.0
## [4,]  96.0
## [5,] 102.0
## 
## $`2`$n
## [1] 8
## 
## $`2`$conf
##          [,1]
## [1,] 81.45871
## [2,] 96.54129
## 
## $`2`$out
## numeric(0)
## 
## $`2`$group
## numeric(0)
## 
## $`2`$names
## [1] "1"

Vererbung am Beispiel verschiedener Wege zur selben Grafik

Am Beispiel von Scatterplots.

Da die Grafiken ‘programmiert’ werden, gibt es bei einer so offenen und modularen Struktur wie bei ggplot meist mehrere Wege, dasselbe zu erreichen. Hier wird das am Beispiel der Verwendung und Übergabe notwendiger Informationen (Dataframe, Zuordnung von Spalten zu Achsen) demonstriert. Dabei wird auch Vererbung mit erläutert.

# mini dataframe
dd <- data.frame(
    x = c( 1, 2, 3, 4, 5, 6, 7, 8),
    y = c( 3, 2, 4, 4, 6, 8, 9, 8),
    g = factor(c(rep('m', 4), rep('f', 4)))
    )
# package ggplot2 has to be loaded
require("ggplot2")
# create a plot object without any defaults or preset parameters/values/geoms/aes ...
pplot <- ggplot()
# add a geom of type scatterplot (geom_point) also including a reference to the data 
pplot + 
  geom_point(data=dd, aes(x=x, y=y))

# create a plot object with some basic information
pplot <- ggplot(data=dd, aes(x=x, y=y))
# we can also use unnamed parameters for aes x and y
pplot <- ggplot(data=dd, aes(x, y))

# add scatterplot using `geom_point()` that herits its parameters from the mother ggplot object 
pplot + 
  geom_point()

# alternative syntax for the same plot using explicit layer()
# the above used geom_point() implicitly generates a layer() what is done here explicitly
# again the base data may be provided by the layer or by the base graphics  object
pplot <- ggplot()
pplot + layer(
  data=dd, 
  mapping=aes(x=x, y=y),
  position = "identity",
  stat="identity",
  geom = "point"
)

# alternatively via herited data of base graphic object pplot, layer() refers to that and only sets the specific parameters stat and geom
pplot <- ggplot(data=dd, aes(x=x, y=y))
pplot + layer(
    mapping = NULL,
  position = "identity",
  stat="identity",
  geom = "point"
)

# finally the same graph using qplot()
qplot(x, y, data=dd)

Wir können ein “leeres” Grafikobjekt erzeugen. Es sind hierbei keinerlei weitere Grunddaten festgelegt, weder ein Dataframe, noch Zuordnungen von Variablen zu Achsen o. ä. Alle Infos werden über Parameter des geom geom_point() geliefert.

Alternativ können wir Grafikobjekt z. B. namens “pplot” erzeugen, das bereits die Angaben zu Dataframe und zur Zuordnung von Variablen zu Achsen enthält. Hierauf greifen alle dem Grafikobjet “pplot” per “+” hinzugefügten Layers automatisch zurück. Unser geom_point() kommt somit ohne jegliche Paramter aus.

Während geom_point() implizit ein layer() erzeugt, können wir den Befehl layer() auch explizit benutzen. Auch hierbei funktioniert die o. a. Vererbung der Parameter aus dem Grundobjekt.

qplot() macht alles implizit, hat aber nicht so viele Einflussmöglichkeiten.

Grafiken auf Basis von mehreren Datenquellen

ggplot Grafiken können in einer Grafik mehrere Datenquellen vom Typ Tibble/Dataframe verwenden. Wir können geom...() einen Parameter data= hinzufügen, der benutzt werden soll. Hierdurch können Rohwerte und aus anderen Berechnungen stammende Ergebnisse in einer Grafik gemeinsam verwendet werden.

require("ggplot2")
# define dataframe 3 groups, gender and two vars (weight and height)
dd1 <- data.frame(
  m.weight = c( 50,  55,  75,  77,  90,  98), 
  m.height = c(165, 184, 170, 179, 167, 182), 
  group = factor(c(rep(1,2),rep(2,2),rep(3,2))), 
  gender = factor(c(rep(c(1,2),3)))
  )
# we might have new weights after some treatment
dd2 <- data.frame(
  m.weight=c( 55,  57,  74,  75,  78,  88), 
  m.height=c(165, 184, 170, 179, 167, 182), 
  group=factor(c(rep(1,2),rep(2,2),rep(3,2))), 
  gender=factor(c(rep(c(1,2),3)))
  )

# we plot t1
( pplot <- ggplot() +  
  geom_point(data = dd1, aes(x=m.height, y=m.weight, shape=group))
)

# we add t2
( pplot2 <- pplot + 
  geom_point(data=dd2, aes(m.height, m.weight, shape=group, color='red'), show.legend=F) 
)

# erase data to keep environment clean
rm(df1)
## Warning in rm(df1): Objekt 'df1' nicht gefunden
rm(df2)
## Warning in rm(df2): Objekt 'df2' nicht gefunden

Extras zu Grafiken hinzfügen, Achsen modifizieren

Auch Beschriftung, Titel, Achsenmodifikationen, Extras etc. sind Layer, die hinzugefügt werden.

# mini dataframe
dd <- data.frame(
    x = c( 1, 2, 3, 4, 5, 6, 7, 8),
    y = c( 3, 2, 4, 4, 6, 8, 9, 8)
    )
# package ggplot2 has to be loaded
require("ggplot2")

# create a plot object with some basic information and a point layer
( pplot <- ggplot(data=dd, aes(x=x, y=y)) + geom_point() )

# we might want to add a title
pplot + 
  ggtitle("Streudiagramm von einigen x und y")

# title can have several lines
pplot + 
  ggtitle("Streudiagramm von einigen x und y \n wenig vertrauenserweckende Werte!")

# maybe some other axis names aditionally to a title?
pplot + 
  labs(title="Streudiagramm von einigen x und y", x = "x regelmäßig steigend", y = "eng, aber nicht vollständig gebunden")

# lets make y a scale between 1 and 10
pplot + 
  labs(title="Streudiagramm von einigen x und y", x = "x regelmäßig steigend", y = "1 < y < 10") +
  ylim(1, 10)

pplot + 
  labs(title="Streudiagramm von einigen x und y", x = "x regelmäßig steigend", y = "1 < y < 10") +
  #ylim(1, 10) +
  scale_y_continuous(breaks=seq(1, 10, 1))  # # Ticks from 1-10, every 1.0

Farben

Farben in ggplot.

Grafiken speichern

Beim Speichern von Grafiken via Skript sind die Möglichkeiten abhängig von der Plattform, auf der wir uns bewegen.

# mini dataframe
dd <- data.frame(
  time  = c("t1", "t2", "t1", "t2"),
    group = c("f", "f", "m", "m"),
    mean  = c(1.6, 1.8, 3.5, 4.1),
    se    = c(0.1, 0.3, 0.3, 0.2)
    )
# package ggplot2 has to be loaded
require("ggplot2")

# create a plot object, define dataframe to use, add gender to differ in colour already in base plot
pplot <- ggplot(dd, x=group, y=mean, aes(group, mean, fill = time))

# create a bar plot
pplot +
  geom_bar(stat="identity", position=position_dodge()) +
  geom_errorbar(aes(ymax = mean + se, ymin= mean - se), position = position_dodge(width=0.7), width=0.2) +
  #geom_point(stat="identity", shape=21, size=5, position=position_dodge(width=0.7), width=0.2)
  geom_point(stat="identity", shape=21, size=5, position=position_dodge(width=0.7))

# now save it to a file in the current working directory
ggsave(file="test.pdf")
## Saving 7 x 5 in image
# ggsave(file="test.jpeg",dpi=72)
# ggsave(file="test.svg",plot=pplot,width=10,height=5)

Multiple Grafiken - mehrere Grafiken auf einer Seite

Ansatz mit facet_grid() für multiple Grafiken bzw. Subgrafiken

# scatterplot of all the pacs items with the scale using faceting
dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_bmi_preprocessed.txt", fileEncoding = "UTF-8")
# or, as UTF-8 is default in tidyverse readr
require(tidyverse)
## Lade nötiges Paket: tidyverse
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✔ tibble  3.1.6     ✔ dplyr   1.0.8
## ✔ tidyr   1.2.0     ✔ stringr 1.4.0
## ✔ readr   2.1.2     ✔ forcats 0.5.1
## ✔ purrr   0.3.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter()    masks stats::filter()
## ✖ dplyr::lag()       masks stats::lag()
## ✖ dplyr::src()       masks Hmisc::src()
## ✖ dplyr::summarize() masks Hmisc::summarize()
dd <- read_tsv("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_bmi_preprocessed.txt")
## Rows: 30 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr  (4): name, gender, bmi_class, bmi_dichotom
## dbl (15): subj, height, weight, grade, c_phys_app, c_good_way, c_dress, c_ba...
## lgl  (1): bmi_normal
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
p <- ggplot(dd, aes(bmi, pacs)) + geom_point()
# With one variable
p + facet_grid(. ~ gender)

p + facet_grid(bmi_dichotom ~ gender)

Alternative Ansätze für multiple Grafiken

In ggplot2 funktioniert das klassische Aufteilen der Ausgabe mit par() leider nicht. Wir können alternativ grid.arrange() aus der library(gridExtra) verwenden.

cf: [http://stackoverflow.com/questions/1249548/side-by-side-plots-with-ggplot2-in-r]

or cookbook receipe multiport

cf. [http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_%28ggplot2%29/]

alternativ: cowplot für differneziertere Grids

require(ggplot2)
require(grid)
## Lade nötiges Paket: grid
require(gridExtra)
## Lade nötiges Paket: gridExtra
## 
## Attache Paket: 'gridExtra'
## Das folgende Objekt ist maskiert 'package:dplyr':
## 
##     combine
#require("gridExtra")
#require(grid)

# create four plots and show them in grid
x <- rnorm(100, 100, 15)
y <- x + 5 + rnorm(100, 0, 5)
dd <- data.frame(x, y)
p1 <- ggplot(dd, aes(x=x, y=y)) + geom_histogram(aes(y= ..density..))
p2 <- ggplot(dd, aes(x=x, y=y)) + geom_histogram(aes(x=y, y=..density..))
p3 <- ggplot(dd, aes(x=x, y=y)) + geom_point()
p4 <- p3 + geom_hline(yintercept=mean(y))
#p1 <- ggplot(dfbmi, x=nation, y=bmi, aes(nation, bmi, fill = gender))
grid.arrange(p1,p2,p3,p4, ncol=2)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Text und Pfeile hinzufügen

require("ggplot2")
dd <- data.frame(
  m.weight=c( 50,  55,  75,  77,  90,  98,     53,  57,  76,  75,  91,  99), 
  m.height=c(165, 184, 170, 179, 167, 182,    166, 183, 171, 179, 174, 183), 
  group=factor(c(rep('a',2),rep('b',2),rep('c',2),rep('a',2),rep('b',2),rep('c',2))), 
  gender=factor(c(rep(c('f', 'm'),6)))
  )

# we add an annotation
ggplot(data=dd, aes(x=m.height, y=m.weight, color=gender)) + 
  geom_point() + 
    geom_text(x=180, y=72, label="important", color="red")

# we add an arrow with label
require(grid)  # needed for arrow
ggplot(data=dd, aes(x=m.height, y=m.weight)) + 
  geom_point() + 
    geom_text(x=174, y=80, label="critical", color="red") +
    geom_segment(aes(x = 174, y = 85, xend = 174, yend = 90), arrow = arrow(length = unit(0.5, "cm")))

# we add an arrow with label
require(grid)  # needed for arrow
ggplot(data=dd, aes(x=m.height, y=m.weight)) + 
  geom_point() + 
    geom_text(x=174, y=83, label="critical", color="red") +
    geom_segment(aes(x = 174, y = 85, xend = 174, yend = 90), arrow = arrow(length = unit(0.5, "cm")), color="red") +
  geom_point(aes(x = 167, y = 90), shape=1, size=10, color="green")

Density Plots in ggplot2()

require(ggplot2)
#Sample data
dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
                   , lines = rep(c("a", "b"), each = 100))
#Plot.
ggplot(dat, aes(x = dens, fill = lines)) + geom_density(alpha = 0.5)

# a normal distribution
df <- data.frame(x=1:100, y=rnorm(100,0,1))
ggplot(df, aes(y)) + stat_function(fun=dnorm, args=list(mean=mean(df$y), sd=sd(df$y)))

Zeitliche Verläufe: Long wide and ggplot

Oft erleichtert es graphische Darstellungen mit ggplot() sehr, wenn die Daten “tidy” sind. Ggf. ist eine Wandlung wide -> long sinnvoll zur leichteren Visualisierung der Daten. Es gibt keinen einfachen Weg, um in ggplot() Messwiederholungsdaten im wide Format auf der X-Achse aufzutragen.

Verstehbeispiel 2*3 reines Messwiederholungsdesign

AV Zahl reproduzierter Silben subj: Versuchsperson gender: ‘f’, ‘m’ mnemotechnik: ‘m’, ‘c’ t1: AV Zeitpunkt 1 t2: AV Zeitpunkt 2 t3: AV Zeitpunkt 3

# we generate data frame in wide format
df.w <- data.frame(
  subj   = c(1,2,3,4),
  gender = c('f', 'f', 'm', 'm'),
  t1c     = c( 4,  5,  7,  6),
  t2c     = c( 6,  5,  9,  8),
  t3c     = c( 7,  6, 12, 10),
  t1m     = c( 8,  6, 15, 10),
  t2m     = c(12,  7, 19, 13),
  t3m     = c(13,  7, 22, 14)
  )
# take a look at it
df.w
##   subj gender t1c t2c t3c t1m t2m t3m
## 1    1      f   4   6   7   8  12  13
## 2    2      f   5   5   6   6   7   7
## 3    3      m   7   9  12  15  19  22
## 4    4      m   6   8  10  10  13  14
df.w$subj <- factor(df.w$subj)

# we could try to visualize using multiple aes in geoms and manual adaptation of x
require(ggplot2)
plw <-  ggplot() +
        geom_point(data=df.w, aes(x=1, y=t1c, group=subj, color=subj, shape=subj)) +
        geom_point(data=df.w, aes(x=2, y=t2c, group=subj, color=subj, shape=subj)) +
        geom_point(data=df.w, aes(x=3, y=t3c, group=subj, color=subj, shape=subj))
plw

# but this is not an elegant way to do it, not at all


# we better go the tidy way ...

# we gather all repeated measure variables at once
require(tidyr)
df.l <- df.w %>% tidyr::gather(key=m_t, value=dv, t1c:t3m)
# we make new columns to specify the repeated measure factors using the position in source column name and preserving source column to control what's happening
df.l %>% tidyr::separate(m_t, c("time", "cond"), 2, 1, remove=F) -> df.l
# we want to have all repeated measures for each person in consecutive lines
df.l %>% dplyr::arrange(subj, cond, time) -> df.l

df.l$subj <- as.factor(df.l$subj)
df.l$cond <- as.factor(df.l$cond)

# with tidy data it tracks down to this ..
require(ggplot2)
pl <-  ggplot(data=df.l, aes(x=time, y=dv, group=subj, color=subj, shape=subj)) + 
    aes(stat='identity') + 
    geom_line(aes(group=subj)) +
    geom_point() +
    facet_wrap(~cond)
    
pl

Legende

  • Legenden werden automatisch erzeugt, wenn eine “dritte” Variable über x und y hinaus ins Spiel kommt. Dies geschieht z. B. über aes(..., group=...), aes(..., color=...), aes(..., shape =...)

  • Bei Farbe: Je nach Datentyp ist die Farbe dann kontinuierlich (stetige Variable, z. B. numerisch) oder gruppenspezifisch (Faktor).

  • Wenn die Legende unterdrückt werden soll: ..., show.legend = FALSE

  • Multiple Legenden bei mehr als 3 dargestellten Variablen.

  • Es gibt eine Reihe von Befehlen zur Manipulation von Legenden:

  • scale_..._discrete()

    1. B. scale_shape_discrete() um die Legende nach einem shape Parameter anzupassen
  • Ein Trick, eine Legende unterzubringen, die gar nichts mit den in der Grafik verwendeten Variablen zu tun hat, ist, eine Variable mit aufzunehmen und unsichtbar zu setzen, z. B. über alpha=0. Dann wird als sichtbarer Effekt nur die Grafik generiert. (plausibler Anwendungsfall?) Das letzte Beispiel unten zeigt das: we draw a layer with alpha=0 that actually hides the points to be plotted but generates the legend

  • we can adapt, what is output in the legend in several ways [https://www.r-graph-gallery.com/239-custom-layout-legend-ggplot2.html]

library(tidyverse)
ds <- read_tsv("https://formr.org/assets/tmp/admin/_43eBqnR8S-ekngSj_Ya9r_MZnbwhk2nD4p2nGHYIrkD.txt?v1590078725")
## New names:
## * `` -> ...1
## Rows: 30 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## dbl (5): ...1, day, trueValue, error, obsValue
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# we generate an categorial variable just for demo reasons
ds$leg <- factor(c(rep("Punkt: Messwert", 10), rep("blau: Trendlinie", 10), rep("grau: Konfidenzintervall", 10)))
fitlmT      <- lm(obsValue ~ day, data = ds)

# no third variable, so no legend
ggplot(ds, aes(day,obsValue)) +
  geom_point() + 
  geom_smooth(method="lm")
## `geom_smooth()` using formula 'y ~ x'

# a third continuous variable causes a color transition
ggplot(ds, aes(day,obsValue, color=trueValue)) +
  geom_point() + 
  geom_smooth(method="lm")
## `geom_smooth()` using formula 'y ~ x'

# a factor causes group specific colors and group specific graphs
# group membership is coded by color
ggplot(ds, aes(day,obsValue, color=leg)) +
  geom_point() + 
  geom_smooth(method="lm")
## `geom_smooth()` using formula 'y ~ x'

# we can suppress legend generation by adding the flag `show.legend` to every geom
ggplot(ds, aes(day,obsValue, color=leg)) +
  geom_point( show.legend = FALSE) + 
  geom_smooth(method="lm",show.legend = FALSE)
## `geom_smooth()` using formula 'y ~ x'

# two more variables over x and y cause 2 legends
ggplot(ds, aes(day,obsValue, color=trueValue, shape=leg)) +
  geom_point() + 
  geom_smooth(method="lm")
## `geom_smooth()` using formula 'y ~ x'

# we can suppress using guide
ggplot(ds, aes(day,obsValue, color=trueValue, shape=leg)) +
  geom_point() + 
  # guides(shape = FALSE) +   # deprecated
  guides(shape = "none") + 
  geom_smooth(method="lm")
## `geom_smooth()` using formula 'y ~ x'

# we can explicitely set legends
ggplot(ds, aes(day,obsValue, shape=leg)) +
  geom_point() + 
  scale_shape_discrete(name = "Dose", labels = c("A", "B", "C")) + 
  geom_smooth(method="lm")
## `geom_smooth()` using formula 'y ~ x'

# we add vars, only to get the legend we want
ggplot(ds, aes(day,obsValue)) +
  geom_point() + 
  geom_smooth(method="lm") + 
  labs(title ="Verlauf über die Tage", x = "Tag der Beobachtung", y = "tägliche Anzahl") +
  geom_point(aes(color=leg), alpha=0) 
## `geom_smooth()` using formula 'y ~ x'

legend

Farben - Colors

If we set the color aestetic for a variable of type factor, the colors are set due to the number of levels of the factor and in the sequence of the factor levels (default alphabetically).

Stackoverflow: background

library(scales)
## 
## Attache Paket: 'scales'
## Das folgende Objekt ist maskiert 'package:purrr':
## 
##     discard
## Das folgende Objekt ist maskiert 'package:readr':
## 
##     col_factor
hue_pal()(5)
## [1] "#F8766D" "#A3A500" "#00BF7D" "#00B0F6" "#E76BF3"
show_col(hue_pal()(5))

# background from the stackoverflow post above
# It is just equally spaced hues around the color wheel, starting from 15:

gg_color_hue <- function(n) {
  hues = seq(15, 375, length = n + 1)
  hcl(h = hues, l = 65, c = 100)[1:n]
}
n = 4
cols = gg_color_hue(n)
cols
## [1] "#F8766D" "#7CAE00" "#00BFC4" "#C77CFF"
# dev.new(width = 4, height = 4)
plot(1:n, pch = 16, cex = 2, col = cols)

dd <- tibble(
  nr = c(1,2,3,4,5),
  yy = c(2, 4, 5, 3, 5.5),
  ff = factor(c('a', 'b', 'b', 'a', 'b'))
)
# dd$ff has two levels
dd$ff
## [1] a b b a b
## Levels: a b
# we get these colors for dd$ff
hue_pal()(2)
## [1] "#F8766D" "#00BFC4"
dd %>% ggplot(aes(x = nr, y = yy, color = ff)) + 
       geom_point() + 
       geom_hline(yintercept = 2.5,   color = hue_pal()(2)[1]) +
       geom_hline(yintercept = 4.833, color = hue_pal()(2)[2])

Missings

In ggplot() default behavior graphs with missings are shown incomplete or interpolated.

require(tidyverse)
dd <-tibble(
  subj = as.factor(c(1,2,3,4,5, 6)),
  grp  = c("T", "C", "T", "C", "T", "C"),
  x.c    = c(11, 12, 13, 14, 15, 16),
  y1.c   = c( 2,  0,  5,  4,  7, 8),
  y2.c   = c( 6,  2,  7, 12,  9, 11),
  y3.c   = c( 9,  8,  8, 14,  11, 15),
  y4.c   = c( 10,  9,  10, 15,  10, 16),
  x.m   = c(11, 12, 13, NA, 15, 16),
  y1.m   = c( NA,  2,  5,  NA,  7, 9),
  y2.m   = c( 4,  NA,  6,  NA,  9, 8),
  y3.m   = c( 6,  NA,  8,  10,  NA, 9),
  y4.m   = c( 8,  5,  NA,  10.5,  12, 11)
)

  
# we convert dd to long format
dd.l <- dd %>% tidyr::gather(time, score, c(y1.c:y4.c,  y1.m:y4.m)) %>% dplyr::arrange(subj)
dd.l <- dd.l %>% tidyr::separate(time, c("time2", "cond"), 2, -1, remove=F)
dd.l$time2 <- dplyr::recode(dd.l$time2, "y1"="t1", "y2"="t2")
dd.l$cond <- dplyr::recode(dd.l$cond, ".c"="compl", ".m"="miss")

require(ggplot2)

dd.l %>% dplyr::filter(cond == "compl") %>% ggplot(aes(x = time2, y = score, group=subj, color=grp)) + 
  stat_summary(fun = mean, geom="point") +
  stat_summary(fun.data = mean_se, geom = "errorbar", width=0.2) +
  stat_summary(fun = mean, geom="line") 

# missings
dd.l %>% dplyr::filter(cond == "miss") %>% ggplot(aes(x = time2, y = score, group=subj, color=subj)) + 
  stat_summary(fun = mean, geom="point") +
  stat_summary(fun.data = mean_se, geom = "errorbar", width=0.2) +
  stat_summary(fun = mean, geom="line") 
## Warning: Removed 7 rows containing non-finite values (stat_summary).
## Removed 7 rows containing non-finite values (stat_summary).
## Removed 7 rows containing non-finite values (stat_summary).

Plotly

Dynamische, interaktive Grafiken

Installation: install.packages("plotly") “Plotly is an R package for creating interactive web-based graphs via plotly’s JavaScript graphing library, plotly.js.” Quelle

Wir stellen hier nur eine Möglichkeit von vielen dar, die das Package bietet. Beliebige ggplot-Grafiken können wir dynamisieren, indem wir ein ggplot-Objekt erstellen und speichern und das dann als Parameter verwenden für plotly::ggplotly().

Danach können wir nach einem Klick in die Grafik mit dem Cursor über die Grafik gehen und es springen viele Infos auf, z. B. die Koordinaten einzelner Datenpunkte, ein Menu zur weiteren Bearbeitung etc.

Ein Beispiel:

library(tidyverse)
dd <- read_tsv("https://formr.org/assets/tmp/admin/_43eBqnR8S-ekngSj_Ya9r_MZnbwhk2nD4p2nGHYIrkD.txt?v1590078725")
## New names:
## * `` -> ...1
## Rows: 30 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## dbl (5): ...1, day, trueValue, error, obsValue
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# we add vars, only to get the legend we want
dd$gar <- factor(rep(1:3, 10))
dd$Legende <- factor(c(rep("Punkt: Messwert", 10), rep("blau: Trendlinie", 10), rep("grau: Konfidenzintervall", 10)))
fitlmT      <- lm(obsValue ~ day, data = dd)


pp <- (ggplot(dd, aes(day,obsValue)) +
  geom_point() + 
  geom_smooth(method="lm") + 
  labs(title ="Verlauf über die Tage", x = "Tag der Beobachtung", y = "tägliche Anzahl") +
  geom_point(aes(color=gar), alpha=0) + 
  scale_colour_identity("Legende", guide = "legend", aesthetics = "colour", breaks=c(1,2,3), labels=c("Wert", "Trend", "KI")) )

plotly::ggplotly(pp)
## `geom_smooth()` using formula 'y ~ x'

Dual Y-axis

Die Grundidee ist eine zweite Beschriftung mit einer umskalierten ersten Y-Achse.

Tutorial

Maps

Landkarten - hier nicht weiter behandelt, nur ein Mini Beispiel:

library(maps)
## 
## Attache Paket: 'maps'
## Das folgende Objekt ist maskiert 'package:purrr':
## 
##     map
outlines <- map("world",xlim=-c(113.8, 56.2),ylim=c(-21.2, 36.2))

Beispiele und Aufgaben

Ein Beispiel mit virtuellen Daten zu Reaktionszeiten und P300 (EEG) html

Ein paar Experimente und Beispielcode: bmi_graphics html

Beispielgrafiken: viele in
body_comarison

Aufgaben variieren

  • “spielen” Sie in den obigen Versteh-Beispielen, indem Sie Daten verändern und den Effekt auf die erzeugten Grafiken beobachten

  • “spielen” Sie in den obigen Versteh-Beispielen mit den Parametern von ggplot

  • gestalten Sie die Beispielgrafiken mit zusätzlichen Hervorhebungen, Erklärungen, Markierungen etc. aus

Aufgabe Datensatz “df_dplyr.txt”

Erstellen Sie für den Beispielatensatz df_dplyr.txt - ein paar Scatterplots (v1, v2, v3) - v1 … v3 als Verläufe in x-Richtung - Boxplot für Geschlecht, Gruppe - Bargraph für Geschlecht, Gruppe - … mit Errorbars - … mit Vorberechnung der aggregierten Werte z. B. unter Anwendung von summarySE() - fassen Sie die Variablen v1 … v3 als Messwiederholungen auf und erstellen Sie eine Grafik, in der der Verlauf gruppenspezifisch ausgegeben wird

require(tidyverse)
dd <- read_delim("http://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt", delim="\t")
## Rows: 12 Columns: 7
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (1): gender
## dbl (6): subj, age, grp, v1, v2, v3
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# or
dd <- read_tsv("http://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
## Rows: 12 Columns: 7
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (1): gender
## dbl (6): subj, age, grp, v1, v2, v3
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dd$gender <- factor(dd$gender)
dd$grp    <- factor(dd$grp)

( pp1 <- dd %>% ggplot(aes(x=v1, y=v2)) +
  geom_point()
)

( pp2 <- dd %>% ggplot(aes(x=v1, y=v3)) +
  geom_point()
)  

( pp3 <- dd %>% ggplot(aes(x=v2, y=v3)) +
  geom_point()
)

gridExtra::grid.arrange(pp1, pp2, pp3, nrow = 1)

# we convert dd to long format
dd.l <- dd %>% tidyr::gather(time, vv, v1:v3) %>% dplyr::arrange(subj)

# if we interprete v1, v2, v3 repeated measures of subjects, we might
( pp4 <- dd.l %>% ggplot(aes(x=time, y=vv, group=subj, color=grp)) +
  geom_point() + 
  geom_line()
)

( pp5 <- dd.l %>% ggplot(aes(x=time, y=vv, group=subj, color=grp)) +
  geom_point() + 
  geom_line() 
)

# {} todo
#   geom_point(aes(group=location, color=location, shape=location), show.legend=FALSE) + 
#   geom_line(aes(group=location, color=location), show.legend=FALSE)
#  stat_summary(data=dd.eu, aes(x=week_nr, y=new_cases_smoothed_per_million_week, group = 1), fun = mean, geom="point", color="black", show.legend=FALSE) +
#  stat_summary(data=dd.eu, aes(x=week_nr, y=new_cases_smoothed_per_million_week, group = 1), fun = mean, geom="line", color="black", show.legend=FALSE) +
#  ggtitle("Cases - Europe: black") +
#  labs (x = "week number in 2021")
#)

gridExtra::grid.arrange(pp1, pp2, pp3, nrow = 1)

Aufgabe economics

In R ist ein Datensatz über ökonomische Verlaufsdaten der USA hinterlegt.

Achtung:

Der Zahlenname Billion steht im deutschen Sprachgebrauch für die Zahl 1000 Milliarden oder 1.000.000.000.000 = 1012, im Dezimalsystem also für eine Eins mit 12 Nullen. 1000 Billionen ergeben eine Billiarde. Der Vorsatz für Maßeinheiten für den Faktor eine Billion ist Tera mit dem Zeichen T. Abgekürzt wird sie mit Bio. oder Bill., wobei Letzteres mit Billiarde verwechselt werden kann.

Das US-amerikanische billion hingegen entspricht der deutschen Milliarde.

  • zeichnen Sie den Verlauf der Arbeitslosenzahlen über die Jahre
  • zeichnen Sie zusätzlich einen Smoother mit ein, um den Langzeit-Trend zu visualisieren
help(economics)
# we make economics accessible by a shorter name, df
df <- economics

pp <- ggplot(data = economics, aes(x = date, y = unemploy))
pp <- pp + geom_line()
pp <- pp + geom_smooth()

pp
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Beispiel l/100km und MpG

1 L/100km entspricht \(100 * 3.79/1.61 = 235.4 mpg\).

  • 1 Gallone = 3.79 Liter (L)
  • 1 Meile = 1.61 Kilometer (km)

mpg -> l/100

\(l/100km = 100 / (mpg * 1.6) * 3.7\)

require(ggplot2)
?mpg
dd <- mpg

require(psych)
## Lade nötiges Paket: psych
## 
## Attache Paket: 'psych'
## Die folgenden Objekte sind maskiert von 'package:scales':
## 
##     alpha, rescale
## Das folgende Objekt ist maskiert 'package:Hmisc':
## 
##     describe
## Die folgenden Objekte sind maskiert von 'package:ggplot2':
## 
##     %+%, alpha
psych::describe(dd)
##               vars   n    mean    sd median trimmed   mad    min  max range
## manufacturer*    1 234    7.76  5.13    6.0    7.68  5.93    1.0   15  14.0
## model*           2 234   19.09 11.15   18.5   18.98 14.08    1.0   38  37.0
## displ            3 234    3.47  1.29    3.3    3.39  1.33    1.6    7   5.4
## year             4 234 2003.50  4.51 2003.5 2003.50  6.67 1999.0 2008   9.0
## cyl              5 234    5.89  1.61    6.0    5.86  2.97    4.0    8   4.0
## trans*           6 234    5.65  2.88    4.0    5.53  1.48    1.0   10   9.0
## drv*             7 234    1.67  0.66    2.0    1.59  1.48    1.0    3   2.0
## cty              8 234   16.86  4.26   17.0   16.61  4.45    9.0   35  26.0
## hwy              9 234   23.44  5.95   24.0   23.23  7.41   12.0   44  32.0
## fl*             10 234    4.63  0.70    5.0    4.77  0.00    1.0    5   4.0
## class*          11 234    4.59  1.99    5.0    4.64  2.97    1.0    7   6.0
##                skew kurtosis   se
## manufacturer*  0.21    -1.63 0.34
## model*         0.11    -1.23 0.73
## displ          0.44    -0.91 0.08
## year           0.00    -2.01 0.29
## cyl            0.11    -1.46 0.11
## trans*         0.29    -1.65 0.19
## drv*           0.48    -0.76 0.04
## cty            0.79     1.43 0.28
## hwy            0.36     0.14 0.39
## fl*           -2.25     5.76 0.05
## class*        -0.14    -1.52 0.13
require(tidyverse)
# we recalculate miles per gallon into liters per 100 km and save it in an additional column
dd$ctl100km <- 100 / (dd$cty * 1.6) * 3.7
dd$hwl100km <- 100 / (dd$hwy * 1.6) * 3.7
# we generate column eco which represents the order from most economic to least economic consumption
dd <- dd %>% arrange(ctl100km)
dd$eco <- 1:nrow(dd)

# we plot city consumption and hiway consumption for the manufacturers
dd %>% ggplot(aes(x=manufacturer, y=ctl100km, color="red")) + geom_point() + geom_point(aes(y=hwl100km, color="blue"))

# we plot average city consumption for the manufacturers
dd %>% ggplot(aes(x=manufacturer, y=ctl100km, color=manufacturer)) + stat_summary(fun.y = mean, geom="point") +
  stat_summary(fun.data = mean_cl_normal, geom = "errorbar", width=0.2, size=1)
## Warning: `fun.y` is deprecated. Use `fun` instead.

# we aggregate data to get a tibble with average consumption per manufacturer (row)
dd %>% dplyr::group_by(manufacturer) %>% dplyr::summarise(ct_m=mean(ctl100km), ct_se=sd(ctl100km)/sqrt(n())) -> dd.m
dd.m <- dd.m %>% dplyr::mutate(upper = ct_m + ct_se, lower = ct_m - ct_se) %>% dplyr::arrange(ct_m)
# we generate column eco which represents the order from most economic to least economic manufacturer in consumption
dd.m$eco <- 1:nrow(dd.m)

dd.m$manuf <- factor(dd.m$manufacturer)

# consumption ordered by manufacturer
dd.m %>% ggplot(aes(x=manufacturer[15:1], y=ct_m, color=manufacturer)) + geom_point(size=3) + 
  geom_errorbar(mapping=aes(x=manufacturer[15:1], ymin=upper, ymax=lower), width=0.2, size=1) 

# consumption ordered by consumption
dd.m %>% ggplot(aes(x=reorder(manuf, eco), y=ct_m, color=reorder(manuf, eco))) + 
  geom_point(size=3) + 
  geom_errorbar(mapping=aes(x=reorder(manuf, eco), ymin=upper, ymax=lower), width=0.2, size=1) 

Interpolieren

… bei missing values in Messwiederholungsverläufen,

Eine Erhebung über 7 Jahre hat aus politischen Gründen in den Jahren 4 und 5 nicht stattgefunden. Die beiden fehlenden Jahre sollen durch geeignete Werte auf individueller Basis geschätzt werden.

require(tidyverse)
dd <-tibble(
  subj = as.factor(c(1,2,3,4,5)),
  y1   = c( 2,  0,  5,  4,  7),
  y2   = c( 6,  2,  7, 12,  9),
  y3   = c( 7,  9,  9, 15, 15),
  y4   = c(NA, NA, NA, NA, NA),
  y5   = c(NA, NA, NA, NA, NA),
  y6   = c(14, 18, 15, 22, 25),
  y7   = c(18, 22, 19, 29, 23)
)
# we convert dd to long format
dd.l <- dd %>% tidyr::gather(year, score, y1:y7) %>% dplyr::arrange(subj)
# and show a graph with the gap between the missing years
dd.l %>% ggplot2::ggplot(aes(x=year, y=score, group=subj, color=subj)) + ggplot2::geom_line() + ggplot2::geom_point(size=5) 
## Warning: Removed 10 rows containing missing values (geom_point).

# we interpolate the missings
dd %>% dplyr::mutate(diff_3_6 = y6 - y3, y4 = y3 + diff_3_6/3, y5 = y6 - diff_3_6 / 3) -> dd
# we convert dd to long format
dd.l <- dd %>% tidyr::gather(year, score, y1:y7) %>% dplyr::arrange(subj)
# and show a graph with the gap between the missing years
dd.l %>% ggplot2::ggplot(aes(x=year, y=score, group=subj, color=subj)) + ggplot2::geom_line() + ggplot2::geom_point(size=5) 

# btw: we could also think of an individual regression line

Versuche stat_summary

require(ggplot2)
year_plot <- ggplot(mpg, aes(x = class, y = cty))
year_plot + stat_summary(fun.y = mean, geom = "point") + 
  stat_summary(fun.y = mean, geom = "line", aes(group = 1)) +
  stat_summary(fun.data = mean_cl_normal, geom = "errorbar", width = 0.2) +
  labs(x = "Art des Autos",
       y = "Miles per Gallon (Stadt)",
       title = "Miles per Gallon in der Stadt nach Art des Autos")
## Warning: `fun.y` is deprecated. Use `fun` instead.
## `fun.y` is deprecated. Use `fun` instead.

mpg_data <- mpg
year_plot <- ggplot(mpg, aes(x = class, y = cty))
year_plot + stat_summary(fun.y = mean, geom = "point") + 
  stat_summary_bin(fun.y = mean, geom = "line")
## Warning: `fun.y` is deprecated. Use `fun` instead.
## `fun.y` is deprecated. Use `fun` instead.
## geom_path: Each group consists of only one observation. Do you need to adjust
## the group aesthetic?

Teilaufgabe sheet_plots

Auf Wunsch der Studierenden ein Abschnitt, wie ihn Johannes Brachem vorgestellt hat am 7.5.2020

library(tidyverse)
# tm <- read_delim("text_messages.dat", delim = "\t")
tm <- read_delim("https://owncloud.gwdg.de/index.php/s/d1QBJpKEpqhPIa9/download", delim = "\t")
## Rows: 50 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (1): Group
## dbl (2): Baseline, Six_months
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
tm$Group %>% unique()
## [1] "Text Messagers" "Controls"
tm_long <- tm %>% gather(Baseline, Six_months, key = "time", value = "score")
p1 <- ggplot(tm_long, aes(x = time, y = score, color = Group))
p1 + 
  stat_summary(fun = "mean",      # Mittelwerte berechnen
               geom = "point",    # Als Punkte anzeigen lassen
               size = 2.5,        # Größe verändern
               aes(shape = Group)
  ) +
  stat_summary(fun.data = mean_cl_boot,
               geom = "errorbar",
               width = 0.2
               ) +
  stat_summary(fun = "mean",
               geom = "line",
               aes(group = Group, linetype = Group)
               ) +
  scale_linetype_manual(values = c(5, 4)) +
  
  labs(x = "Zeit", 
       y = "Grammatik-Score", 
       title = "Plot-Titel",
       color = "Gruppe",
       shape = "Gruppe",
       linetype = "Gruppe"
       ) +
  NULL

both solutions are sort of a trick because legend generation has to be triggered …

Check

Plots are cool and help us to understand statistics.

Some Points to understand

  • Graphs are programmed in R, there is no interactive graphical direct manipulative modification

  • Plots are R-objects with attributes (components or layers), a container that keeps all information to generate a plot

  • connect raw data - aggregating functions - plot-types - scales etc - subsamples

  • Layers are responsible for creating the objects that we perceive on the plot. A layer is composed of five parts:

    • Data
    • Aesthetic mappings.
    • A statistical transformation (stat). Generates a layer.
    • A geometric object (geom). Generates a layer.
    • A position adjustment.
  • the complete process behind:

    mastery-schema.png

    source: ggplot2 book

  • the cheat sheet ggplot, a great point to learn about the possibilities

Some hints

+ has to be at the end of a line and not at the beginning

require(tidyverse)
dd <- read_tsv("http://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
# this works
pp <- ggplot(dd, aes(x = age, y = v1)) +
   geom_point()
pp
# this does not work
pp <- ggplot(dd, aes(x = age, y = v1))
   + geom_point()

understand inheritance

require(tidyverse)
dd <- read_tsv("http://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
# geom_point knows which data to show, because it inherits dd and aes from it's mother object
pp <- ggplot(dd, aes(x = age, y = v1)) +
   geom_point()
# but everything can be overwritten ...
pp <- ggplot(dd, aes(x = age, y = v1)) +
   geom_point() +
   geom_point(aes(y=v2), color = "red")
   # the second geom_point() inherits dd and aes(y = v1), aes(x) is overwritten by v2

pp

factors on axes: the sequence matters

library(tidyverse)
dd <- readr::read_tsv("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_bmi_preprocessed.txt")
## Rows: 30 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr  (4): name, gender, bmi_class, bmi_dichotom
## dbl (15): subj, height, weight, grade, c_phys_app, c_good_way, c_dress, c_ba...
## lgl  (1): bmi_normal
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# default factor ordering by alphabet
dd$f_bmi_class <- factor(dd$bmi_class)
head(dd$f_bmi_class)
## [1] normal low    obese  low    high   low   
## Levels: high low normal obese
# sequence from low to high
dd$of_bmi_class <- factor(dd$bmi_class, levels = c("low", "normal", "high", "obese"))
head(dd$of_bmi_class)
## [1] normal low    obese  low    high   low   
## Levels: low normal high obese
# factor order matters in ggplot
ggplot(dd, aes(x = f_bmi_class, y = bmi)) +
   stat_summary(fun = mean, color ="red") +
   geom_point()
## Warning: Removed 4 rows containing missing values (geom_segment).

ggplot(dd, aes(x = of_bmi_class, y = bmi)) +
   stat_summary(fun = mean, color ="red") +
   geom_point()
## Warning: Removed 4 rows containing missing values (geom_segment).

long format is our friend (tidy data)

See long wide and ggplot

The () trick

If we want to store our ggplot-output in an graph object and show it at the same time, we can use a pair of () around it. ( my_graph <- ggplot(...) + ....)

library(tidyverse)
dd <- readr::read_tsv("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_bmi_preprocessed.txt")
## Rows: 30 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr  (4): name, gender, bmi_class, bmi_dichotom
## dbl (15): subj, height, weight, grade, c_phys_app, c_good_way, c_dress, c_ba...
## lgl  (1): bmi_normal
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# we see the plot immediately but it is not stored
dd %>% ggplot(aes(x=bmi_class, y=bodysatisf, group=gender, color=gender)) + stat_summary(fun=mean) + geom_point()
## Warning: Removed 8 rows containing missing values (geom_segment).

# we store a plot object but we don't see it
plot1 <- dd %>% ggplot(aes(x=bmi_class, y=bodysatisf, group=gender, color=gender)) + stat_summary(fun=mean) + geom_point()
# to see plot1 we have to call it
plot1
## Warning: Removed 8 rows containing missing values (geom_segment).

# we create a graph, stor it in a result object _and_ see it by putting () around it
( plot2 <- dd %>% ggplot(aes(x=bmi_class, y=bodysatisf, group=gender, color=gender)) + stat_summary(fun=mean) + geom_point() )
## Warning: Removed 8 rows containing missing values (geom_segment).

Screencast

  • ggplot() - basic ideas and some hints StudIP - ownCloud

  • colors in ggplot() - Farben und ihr gezielter Einsatz StudIP ownCloud

  • legends in ggplot() - Legenden - gezielte Manipulationen StudIP ownCloud

  • multiple data in ggplot() - eine Grafik mit Daten aus mehreren Datenquellen StudIP ownCloud

Version: 07 Oktober, 2022 16:33