Chapter 8 Operationen bzw. Transformationen über Zeilen hinweg

8.1 Base R

Base R hat eine ganze Familie von Funktionen für die wiederholte Anwendung derselben Operation: https://statologie.de/apply-lapply-sapply-und-tapply-r/

8.1.1 rowMeans() und rowSums() aus base

Das Base-Package von R stellt zeilen- und spaltenweises Summieren und Mitteln zur Verfügung über die Befehle rowMeans() und rowSums() bzw. colMeans() und colSums()

8.1.2 apply() again

apply() hat als zweiten Parameter eine “Richtung”, 1 ist zeilenweises, 2 ist spaltenweises Vorgehen. Spalten von Datenmatrizen speichern meist Variablen über Beobachtungen hinweg. apply(..., 2, ...) führt insofern “vertikale” Operationen aus, also Aktionen innerhalb einer oder mehrerer Variablen.

Da apply() eine Funktion übergeben bekommt, die es anwenden soll, ist es universell.

# create sample dataframe
dd <-data.frame(
  subj   = c(1, 2, 3, 4, 5, 6, 7, 8, 9),
  grade1 = c(1.0, 2.7, 3.7, 1.3, 1.7, 1.0, 3.3, 4.0, 3.7),
  grade2 = c(4.0, 3.0, 1.3, 1.3, 1.0, 1.3, 2.7, 4.0, 3.3),
  grade3 = c(1.3, 2.3, 2.7, 1.0, 1.3, 1.3, 2.3, 3.7, 3.0)
)
# alternatively
dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_grades_mini.txt")

# calculate mean of grade1 simply by slicing one column
mean(dd[,2])
## [1] 2.488889
# we use colMeans()
colMeans(dd[,2:4])
##   grade1   grade2   grade3 
## 2.488889 2.433333 2.100000
# ... and we can use apply()
apply(dd[,2:4], 2, mean)
##   grade1   grade2   grade3 
## 2.488889 2.433333 2.100000
# when we access a line as a whole, we compute nonsense
rowMeans(dd[2,])
##   2 
## 2.5
mean(as.numeric(dd[2,]))
## [1] 2.5
# we want to get mean grade of subj 2
mean(as.numeric(dd[2,2:4]))
## [1] 2.666667
mean(as.numeric(dd[2,c('grade1', 'grade2', 'grade3')]))
## [1] 2.666667

Mit der Kombination aus Slicing und apply() können wir gezielte Datenmodifikationen machen.

apply() hat normalerweise 3 Parameter - den Teil-DataFrame, auf den es angewendet werden soll - eine Richtung (1 ist zeilenweise, 2 ist spaltenweise) - eine Funktion, die zur Anwendung kommen soll - ggf. können weitere Argumente für die Funktion angehängt werden

dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_grades_mini.txt")

# mean grades of the first 5 observations
# we could use colMeans()
colMeans(dd[1:5, c('grade1', 'grade2', 'grade3')])
## grade1 grade2 grade3 
##   2.08   2.12   1.72
# apply() is more generic ...
apply(dd[1:5, c('grade1', 'grade2', 'grade3')], 2, mean)
## grade1 grade2 grade3 
##   2.08   2.12   1.72
# or robust estimators of column means 
# getting rid of the 20% most extreme values and calculating the mean from the rest of the data
apply(dd[,2:4], 2, mean, trim=0.2)
##   grade1   grade2   grade3 
## 2.485714 2.414286 2.028571

8.2 Tidyverse: dplyr::summarize()

8.2.1 Aktionen über Beobachtungen hinweg - spaltenweise Datenmodifikationen und Transformationen - dplyr::summarize()

Mit dplyr::summarize() führen wir spaltenweise Operationen aus. Piping mit %>% verknüpft Einzelschritte und macht die Aktionen verständlicher.

require(tidyverse)
dd <- readr::read_tsv("https://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.
# require(dplyr)
# n of observations
dd %>% dplyr::summarize(n())
## # A tibble: 1 × 1
##   `n()`
##   <int>
## 1    12
# a single column
dd %>% dplyr::summarize(mw = mean(v2))
## # A tibble: 1 × 1
##      mw
##   <dbl>
## 1  55.8
# all columns
dd %>% dplyr::summarize_each(funs(mean))
## Warning: `summarise_each_()` was deprecated in dplyr 0.7.0.
## Please use `across()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
## Warning: `funs()` was deprecated in dplyr 0.8.0.
## Please use a list of either functions or lambdas: 
## 
##   # Simple named list: 
##   list(mean = mean, median = median)
## 
##   # Auto named with `tibble::lst()`: 
##   tibble::lst(mean, median)
## 
##   # Using lambdas
##   list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
## Warning in mean.default(gender): Argument ist weder numerisch noch boolesch: gebe NA zurück
## # A tibble: 1 × 7
##    subj gender   age   grp    v1    v2    v3
##   <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1   6.5     NA    27     2  52.1  55.8    53
# not so useful, v1 ... v3 only
dd %>% dplyr::select(v1:v3) %>% dplyr::summarize_each(funs(mean))
## # A tibble: 1 × 3
##      v1    v2    v3
##   <dbl> <dbl> <dbl>
## 1  52.1  55.8    53

dplyr::summarize() entfaltet seine Möglichkeiten erst wirklich in Kombination mit dplyr::group_by(), was in groupwise dargestellt wird.

Der Spezialaspekt Aggregation mit und ohne “Collapsing” ist dargestellt in collapsing

8.3 Referenzen

Data Wrangling Cheatsheet