‘pliers’: Zange
Datenaufbereitung in R heißt normalerweise, sich intensiv mit dem Thema ‘slicing’ auseinanderzusetzen ../transformation/transformation_base.html.
Dies ist sehr stark orientiert an Programmierkonzepten und einem “Gefühl für Syntax”, besonders dann, wenn es Probleme gibt. Als Alternative zu diesem Vorgehen ist das Paket dplyr
entstanden, das vieles bei der Datenaufbereitung in R intuitiver und einfacher macht.
Das Package dplyr stellt eine Sammlung von Befehlen zur Datenmanipulation zur Verfügung. Dem Paket liegt eine Grammatik zur Datenaufbereitung zugrunde (A Grammar of Data Manipulation). Es wurde entwickelt von Hadley Wickham
Zentral ist hierbei das Konzept “gutstrukturierter Daten” (“tidy data”). Siehe hierzu Hadley Wickhams Artikel zu tidy data, auch lokal.
Alle dplyr Befehle erwarten als ersten Parameter einen Dataframe/Tibble und geben einen Dataframe/Tibble als Ergebnis zurück. Das Verständnis, was in R ein Dataframe bzw. Tibble ist, wird in diesem Tutorial vorausgesetzt.
Wir stellen hier einige der Befehle (verbs
) vor, die dplyr()
zur Verfügung stellt, sowie jeweils einige Beispiele hierzu.
Alle Erläuterungen benutzen einen kleinen Beispiel-Datensatz, die in einem dataframe namens df
geladen sind.
# get some data to play with
require(tidyverse)
## Loading required package: tidyverse
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.3 ✓ purrr 0.3.4
## ✓ tibble 3.1.0 ✓ dplyr 1.0.5
## ✓ tidyr 1.1.3 ✓ stringr 1.4.0
## ✓ readr 1.4.0 ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# take a look at the data: 12 observations, 7 variables
df
## # A tibble: 12 x 7
## subj gender age grp v1 v2 v3
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8
## 2 2 f 33 2 67 73 66
## 3 3 f 47 3 86 87 91
## 4 4 f 10 1 64 68 67
## 5 5 f 21 2 40 46 44
## 6 6 f 30 3 26 34 28
## 7 7 m 51 1 64 66 64
## 8 8 m 13 2 61 66 64
## 9 9 m 17 3 67 67 67
## 10 10 m 25 1 38 36 35
## 11 11 m 33 2 22 25 21
## 12 12 m 27 3 81 86 81
“klassisch” mein hier, Verwenden von Slicing-Techniken (Subsetting) in Kombination mit Assigning-Techniken
… verschachtelte Befehle sind unübersichtlich, fehlerträchtig und führen schnell zu sehr kryptischen Ausdrücken
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# find v-values of all women aged 25 or more
df[df$gender == "f" & df$age >= 25, c('v1', 'v2', 'v3')]
## # A tibble: 3 x 3
## v1 v2 v3
## <dbl> <dbl> <dbl>
## 1 67 73 66
## 2 86 87 91
## 3 26 34 28
# mean of the above values per subject
apply(df[df$gender == "f" & df$age >= 25, c('v1', 'v2', 'v3')], 2, mean)
## v1 v2 v3
## 59.66667 64.66667 61.66667
# make all the above to a small table, means attached at the right
cbind(df[df$gender == "f" & df$age >= 25, c('v1', 'v2', 'v3')], apply(df[df$gender == "f" & df$age >= 25, c('v1', 'v2', 'v3')], 2, mean))
## v1 v2 v3 apply(df[df$gender == "f" & df$age >= 25, c("v1", "v2", "v3")],
## v1 67 73 66 59.66667
## v2 86 87 91 64.66667
## v3 26 34 28 61.66667
filter()
ähnlich subset()
für Teilstichprobenarrange()
zum geordneten Ausgebenselect()
Variablenauswahlmutate()
zum Erzeugen neuer Variablen, z. B. durch Verrechnung andererdistinct()
für Ausprägungen und Ausprägungskombinationensummarise()
aggregierenfilter()
für TeilstichprobenWir können Teilstichproben erhalten, indem wir eine oder mehrere Bedingungen angeben, die die Beobachtungen erfüllen müssen, um ausgegeben zu werden.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
#require(dplyr)
# verb filter: get observertions that comply certain conditions
# get all women
dplyr::filter(df, gender=='f')
## # A tibble: 6 x 7
## subj gender age grp v1 v2 v3
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8
## 2 2 f 33 2 67 73 66
## 3 3 f 47 3 86 87 91
## 4 4 f 10 1 64 68 67
## 5 5 f 21 2 40 46 44
## 6 6 f 30 3 26 34 28
# we can use a combination of several conditions: get all men of group 2
dplyr::filter(df, gender=='m', grp==2)
## # A tibble: 2 x 7
## subj gender age grp v1 v2 v3
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 8 m 13 2 61 66 64
## 2 11 m 33 2 22 25 21
arrange()
zum geordneten AusgebenWir können einen Dataframe vielfältig umordnen lassen.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# verb arrange: reorder data frames
# sort by one variable: group membership
dplyr::arrange(df, grp)
## # A tibble: 12 x 7
## subj gender age grp v1 v2 v3
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8
## 2 4 f 10 1 64 68 67
## 3 7 m 51 1 64 66 64
## 4 10 m 25 1 38 36 35
## 5 2 f 33 2 67 73 66
## 6 5 f 21 2 40 46 44
## 7 8 m 13 2 61 66 64
## 8 11 m 33 2 22 25 21
## 9 3 f 47 3 86 87 91
## 10 6 f 30 3 26 34 28
## 11 9 m 17 3 67 67 67
## 12 12 m 27 3 81 86 81
# we may sort by various variables simultaneously: get highest to lowest v1 scores per group
dplyr::arrange(df, grp, desc(v1))
## # A tibble: 12 x 7
## subj gender age grp v1 v2 v3
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 4 f 10 1 64 68 67
## 2 7 m 51 1 64 66 64
## 3 10 m 25 1 38 36 35
## 4 1 f 17 1 9 16 8
## 5 2 f 33 2 67 73 66
## 6 8 m 13 2 61 66 64
## 7 5 f 21 2 40 46 44
## 8 11 m 33 2 22 25 21
## 9 3 f 47 3 86 87 91
## 10 12 m 27 3 81 86 81
## 11 9 m 17 3 67 67 67
## 12 6 f 30 3 26 34 28
select()
Variablenauswahl (Spalten)Wir können nur eine Untermenge der zur Verfügung stehenden Variablen auswählen.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# verb select: get certain columns
# get subject, gender and grp; we provide a simple list of the variables
dplyr::select(df, subj, gender, age, grp)
## # A tibble: 12 x 4
## subj gender age grp
## <dbl> <chr> <dbl> <dbl>
## 1 1 f 17 1
## 2 2 f 33 2
## 3 3 f 47 3
## 4 4 f 10 1
## 5 5 f 21 2
## 6 6 f 30 3
## 7 7 m 51 1
## 8 8 m 13 2
## 9 9 m 17 3
## 10 10 m 25 1
## 11 11 m 33 2
## 12 12 m 27 3
# we may benefit from the sequence of variables in the dataframe using the ':' operator to get the above
dplyr::select(df, subj:grp)
## # A tibble: 12 x 4
## subj gender age grp
## <dbl> <chr> <dbl> <dbl>
## 1 1 f 17 1
## 2 2 f 33 2
## 3 3 f 47 3
## 4 4 f 10 1
## 5 5 f 21 2
## 6 6 f 30 3
## 7 7 m 51 1
## 8 8 m 13 2
## 9 9 m 17 3
## 10 10 m 25 1
## 11 11 m 33 2
## 12 12 m 27 3
# we may even get all variables that share some naming convention: get all variables whichs name starts with letter "v"
dplyr::select(df, starts_with('v'))
## # A tibble: 12 x 3
## v1 v2 v3
## <dbl> <dbl> <dbl>
## 1 9 16 8
## 2 67 73 66
## 3 86 87 91
## 4 64 68 67
## 5 40 46 44
## 6 26 34 28
## 7 64 66 64
## 8 61 66 64
## 9 67 67 67
## 10 38 36 35
## 11 22 25 21
## 12 81 86 81
# we can get the same, using regular expressions: variable names first letter is v and it continues with at least one more character
dplyr::select(df, matches("[v]+"))
## # A tibble: 12 x 3
## v1 v2 v3
## <dbl> <dbl> <dbl>
## 1 9 16 8
## 2 67 73 66
## 3 86 87 91
## 4 64 68 67
## 5 40 46 44
## 6 26 34 28
## 7 64 66 64
## 8 61 66 64
## 9 67 67 67
## 10 38 36 35
## 11 22 25 21
## 12 81 86 81
# search variable that contains certain substring: all names with "e"
dplyr::select(df, contains('e'))
## # A tibble: 12 x 2
## gender age
## <chr> <dbl>
## 1 f 17
## 2 f 33
## 3 f 47
## 4 f 10
## 5 f 21
## 6 f 30
## 7 m 51
## 8 m 13
## 9 m 17
## 10 m 25
## 11 m 33
## 12 m 27
mutate()
zum Erzeugen neuer Variablen, z. B. durch Verrechnung andererWir können Variablen verändern und neue Variablen auf Basis von bestehenden generieren. Definierte Variablen können sofort verwendet werden, auch im selben Ausdruck schon.
require(tidyverse)
# require(dplyr)
# df <- read_tsv("http://134.76.136.204/data/div/df_dplyr.txt")
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
df$gender <- factor(df$gender)
# verb mutate: create new variables
# rescale v1 to vary between 0 and 1
dplyr::mutate(df, v1q = v1 / 100)
## # A tibble: 12 x 8
## subj gender age grp v1 v2 v3 v1q
## <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 0.09
## 2 2 f 33 2 67 73 66 0.67
## 3 3 f 47 3 86 87 91 0.86
## 4 4 f 10 1 64 68 67 0.64
## 5 5 f 21 2 40 46 44 0.4
## 6 6 f 30 3 26 34 28 0.26
## 7 7 m 51 1 64 66 64 0.64
## 8 8 m 13 2 61 66 64 0.61
## 9 9 m 17 3 67 67 67 0.67
## 10 10 m 25 1 38 36 35 0.38
## 11 11 m 33 2 22 25 21 0.22
## 12 12 m 27 3 81 86 81 0.81
# inversion of variable v2 that varies between 0 and 100
dplyr::mutate(df, v2_inv = 100 - v2)
## # A tibble: 12 x 8
## subj gender age grp v1 v2 v3 v2_inv
## <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 84
## 2 2 f 33 2 67 73 66 27
## 3 3 f 47 3 86 87 91 13
## 4 4 f 10 1 64 68 67 32
## 5 5 f 21 2 40 46 44 54
## 6 6 f 30 3 26 34 28 66
## 7 7 m 51 1 64 66 64 34
## 8 8 m 13 2 61 66 64 34
## 9 9 m 17 3 67 67 67 33
## 10 10 m 25 1 38 36 35 64
## 11 11 m 33 2 22 25 21 75
## 12 12 m 27 3 81 86 81 14
# age in days
dplyr::mutate(df, age_days = age * 365)
## # A tibble: 12 x 8
## subj gender age grp v1 v2 v3 age_days
## <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 6205
## 2 2 f 33 2 67 73 66 12045
## 3 3 f 47 3 86 87 91 17155
## 4 4 f 10 1 64 68 67 3650
## 5 5 f 21 2 40 46 44 7665
## 6 6 f 30 3 26 34 28 10950
## 7 7 m 51 1 64 66 64 18615
## 8 8 m 13 2 61 66 64 4745
## 9 9 m 17 3 67 67 67 6205
## 10 10 m 25 1 38 36 35 9125
## 11 11 m 33 2 22 25 21 12045
## 12 12 m 27 3 81 86 81 9855
# newly generated variables can be used within the same operation
dplyr::mutate(df, age_days = age * 365, age_months = age_days / 30)
## # A tibble: 12 x 9
## subj gender age grp v1 v2 v3 age_days age_months
## <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 6205 207.
## 2 2 f 33 2 67 73 66 12045 402.
## 3 3 f 47 3 86 87 91 17155 572.
## 4 4 f 10 1 64 68 67 3650 122.
## 5 5 f 21 2 40 46 44 7665 256.
## 6 6 f 30 3 26 34 28 10950 365
## 7 7 m 51 1 64 66 64 18615 620.
## 8 8 m 13 2 61 66 64 4745 158.
## 9 9 m 17 3 67 67 67 6205 207.
## 10 10 m 25 1 38 36 35 9125 304.
## 11 11 m 33 2 22 25 21 12045 402.
## 12 12 m 27 3 81 86 81 9855 328.
Achtung: Funktionen wie mean()
oder sum()
etc. funktionieren hier nicht, wie vielleicht erwartet zeilenweise, sondern setzen den Grand Mean bei mean()
ein. Den zeilenweisen Effekt bekommt man über rowwise()
(s. u.).
distinct()
für Ausprägungen und AusprägungskombinationenWir können Ausprägungen von Variablen auflisten, auch Kombinationen von Ausprägungen, die im Datensatz vorkommen.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# verb distinct: the first occurance of any distinct observation is shown
# do we have men and women in the sample?
dplyr::distinct(df, gender)
## # A tibble: 2 x 1
## gender
## <chr>
## 1 f
## 2 m
# which group levels are available?
dplyr::distinct(df, grp)
## # A tibble: 3 x 1
## grp
## <dbl>
## 1 1
## 2 2
## 3 3
# we can also look for combinations or variables: which combinations of gender and grp can be found in the data?
dplyr::distinct(df, gender, grp)
## # A tibble: 6 x 2
## gender grp
## <chr> <dbl>
## 1 f 1
## 2 f 2
## 3 f 3
## 4 m 1
## 5 m 2
## 6 m 3
summarise()
aggregierenWir können Variablen zusammenfassen und vielfältige Operationen auf sie ausführen.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# verb summarise: aggregate data by column
# mean of v1
dplyr::summarise(df, mean(c(v1)))
## # A tibble: 1 x 1
## `mean(c(v1))`
## <dbl>
## 1 52.1
# grand mean of variables v1, v2, and v3
dplyr::summarise(df, mean(c(v1, v2, v3)))
## # A tibble: 1 x 1
## `mean(c(v1, v2, v3))`
## <dbl>
## 1 53.6
# mean of special columns
dplyr::summarise(df, mean(v1), mean(v3))
## # A tibble: 1 x 2
## `mean(v1)` `mean(v3)`
## <dbl> <dbl>
## 1 52.1 53
# get mean, standard deviation and n of v2, result only
dplyr::summarise(df, mean(v2), sd(v2), n())
## # A tibble: 1 x 3
## `mean(v2)` `sd(v2)` `n()`
## <dbl> <dbl> <int>
## 1 55.8 23.7 12
# get the same named
dplyr::summarise(df, v2_m = mean(v2), v2_sd = sd(v2), v2_n = n())
## # A tibble: 1 x 3
## v2_m v2_sd v2_n
## <dbl> <dbl> <int>
## 1 55.8 23.7 12
summarise_all()
für wiederholtes summarise()
über mehrere VariablenEin typischer Anwendungsfall mehrfacher Aktionen ist, dass dieselbe Operation auf viele Variablen ausgeführt werden soll. Hierzu dient der Befehl summarise_all()
.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# create a temporary dataframe
df.t <- dplyr::select(df, age, v1, v2, v3)
# we might be interested in the means of all variables
dplyr::summarise_all(df.t, funs(mean))
## 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))
## # A tibble: 1 x 4
## age v1 v2 v3
## <dbl> <dbl> <dbl> <dbl>
## 1 27 52.1 55.8 53
# we can apply for several functions at a time
# f. e. we might want to check the plausibility of data by controlling the range of answers
dplyr::summarise_all(df.t, funs(min, max, sd, mean))
## # A tibble: 1 x 16
## age_min v1_min v2_min v3_min age_max v1_max v2_max v3_max age_sd v1_sd v2_sd
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 10 9 16 8 51 86 87 91 12.7 24.5 23.7
## # … with 5 more variables: v3_sd <dbl>, age_mean <dbl>, v1_mean <dbl>,
## # v2_mean <dbl>, v3_mean <dbl>
# we delete the temporary dataframe, we have better options ...
rm(df.t)
group_by()
Möchten wir über Teilgruppen hinweg immer wieder dasselbe tun, beispielsweise einen Mittelwert über Variablen haben, müssen wir den summarise()
Befehl nicht immer wieder auf vorher ausgewählte, einzelne Teilgruppen ausführen. Mit dem Befehl group_by
können wir die relevanten Teilgruppen einmal festlegen und dann über diese Teilgruppen Aktionen ausführen.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# group by: get the same for several subgroups
df_grouped <- dplyr::group_by(df, grp)
# get means of v1, v2 and v3 for each group
dplyr::summarise(df_grouped, mean(v1), mean(v2), mean(v3) )
## # A tibble: 3 x 4
## grp `mean(v1)` `mean(v2)` `mean(v3)`
## <dbl> <dbl> <dbl> <dbl>
## 1 1 43.8 46.5 43.5
## 2 2 47.5 52.5 48.8
## 3 3 65 68.5 66.8
# get means of v1, v2 and v3 for each group
dplyr::summarise(df_grouped, mean(v1), sd(v1), mean(v2), sd(v2), mean(v3), sd(v3) )
## # A tibble: 3 x 7
## grp `mean(v1)` `sd(v1)` `mean(v2)` `sd(v2)` `mean(v3)` `sd(v3)`
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 43.8 26.2 46.5 25.1 43.5 27.7
## 2 2 47.5 20.6 52.5 21.6 48.8 21.0
## 3 3 65 27.2 68.5 24.8 66.8 27.6
%>%
Häufig braucht man für eine Datenmodifikation mehrere Teilschritte. Beispielsweise könnte man für eine Teilgruppe eine Aktion über eine Teilmenge der Variablen wollen. Hier bräuchte man also eine Kombination aus filter()
und select()
. Nun könnte man das erreichen, in dem man die Ergebnisse der Zwischenschritte immer in einem Dataframe speichert und im nachfolgenden Schritt wieder als Parameter übergibt. Da dies aber ein häufiges Anliegen ist, sieht dplyr
hierfür eine verkürzte Schreibweise vor: %>%
. Wegen des Prinzips von dplyr
, immer einen Dataframe als ersten Parameter zu erwarten, auf das die geforderten Aktionen ausgeübt werden und einen Dataframe als Ergebnis zurückzugeben, wird diese verkürzte Anweisungsart möglich.
Das Ergebnis einer Kette von Teilschritten kann, wie gewohnt, mit dem Zuweisugsoperator ->
, <-
, oder =
als Ergebnis-Dataframe gespeichert werden.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# chained actions using %>%
# we might want to do something with the three variables v1, v2, and v2 for women only
# we could do this step by step by saving the resulting dataframes
df.f <- dplyr::filter(df, gender=="f")
dplyr::select(df.f, v1:v3)
## # A tibble: 6 x 3
## v1 v2 v3
## <dbl> <dbl> <dbl>
## 1 9 16 8
## 2 67 73 66
## 3 86 87 91
## 4 64 68 67
## 5 40 46 44
## 6 26 34 28
# but we have as shortcut for that: the resulting dataframe of the filter() is passed automatically as first parameter to select()
# the select() does not get a dataframe as first parameter, this is done implicitly
dplyr::filter(df, gender=="f") %>% dplyr::select(v1:v3)
## # A tibble: 6 x 3
## v1 v2 v3
## <dbl> <dbl> <dbl>
## 1 9 16 8
## 2 67 73 66
## 3 86 87 91
## 4 64 68 67
## 5 40 46 44
## 6 26 34 28
# alternative
df %>% dplyr::filter(gender=="f") %>% dplyr::select(v1:v3)
## # A tibble: 6 x 3
## v1 v2 v3
## <dbl> <dbl> <dbl>
## 1 9 16 8
## 2 67 73 66
## 3 86 87 91
## 4 64 68 67
## 5 40 46 44
## 6 26 34 28
# the chain migth be longer ...
dplyr::filter(df, gender=="f") %>% dplyr::group_by(grp) %>% dplyr::select(v1:v3) %>% dplyr::summarise_each(funs(mean))
## Warning: `summarise_each_()` was deprecated in dplyr 0.7.0.
## Please use `across()` instead.
## Adding missing grouping variables: `grp`
## # A tibble: 3 x 4
## grp v1 v2 v3
## <dbl> <dbl> <dbl> <dbl>
## 1 1 36.5 42 37.5
## 2 2 53.5 59.5 55
## 3 3 56 60.5 59.5
rowwise()
, die Probleme damit und die Ansätze zu LösungenHäufig ist es notwendig, bei jeder einzelnen Beobachtung aus einer oder auch mehreren Variablen eine neue Variable zu berechnen. Typische Beispiele hierfür sind: Aus Einzelitems eines Fragebogens Summen- oder Mittelwerte zu berechnen, die dann als Ausprägung auf einer Eigenschaftsdimension interpretiert werden. Ein inhaltliches Beispiel wäre im NEO-FFI das Mitteln über die 12 Neurotizismus-Items als Neurotizismus-Skala.
Zentral für zeilenweise Modifikationen ist hierbei der Befehl rowwise()
.
Mit mutate()
können wir beliebige, auch selbst definierte Funktionen zeilenweise auf die Daten anwenden.
require(tidyverse)
dd <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# verb: rowwise()
# we might want to have the individual means of the three variables v1 to v3
dplyr::rowwise(dd) %>% dplyr::mutate(v_mean = mean(c(v1, v2, v3)))
## # A tibble: 12 x 8
## # Rowwise:
## subj gender age grp v1 v2 v3 v_mean
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 11
## 2 2 f 33 2 67 73 66 68.7
## 3 3 f 47 3 86 87 91 88
## 4 4 f 10 1 64 68 67 66.3
## 5 5 f 21 2 40 46 44 43.3
## 6 6 f 30 3 26 34 28 29.3
## 7 7 m 51 1 64 66 64 64.7
## 8 8 m 13 2 61 66 64 63.7
## 9 9 m 17 3 67 67 67 67
## 10 10 m 25 1 38 36 35 36.3
## 11 11 m 33 2 22 25 21 22.7
## 12 12 m 27 3 81 86 81 82.7
# just to note: without rowwise() this would not work correctly
dplyr::mutate(dd, v_mean = mean(c(v1, v2, v3))) # caution: THIS IS WRONG
## # A tibble: 12 x 8
## subj gender age grp v1 v2 v3 v_mean
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 53.6
## 2 2 f 33 2 67 73 66 53.6
## 3 3 f 47 3 86 87 91 53.6
## 4 4 f 10 1 64 68 67 53.6
## 5 5 f 21 2 40 46 44 53.6
## 6 6 f 30 3 26 34 28 53.6
## 7 7 m 51 1 64 66 64 53.6
## 8 8 m 13 2 61 66 64 53.6
## 9 9 m 17 3 67 67 67 53.6
## 10 10 m 25 1 38 36 35 53.6
## 11 11 m 33 2 22 25 21 53.6
## 12 12 m 27 3 81 86 81 53.6
# building questionnaire scales often requires to invert items before aggregating them
dplyr::rowwise(dd) %>% dplyr::mutate(v2_i = 100 - v2) %>% dplyr::mutate(v_mean = mean(c(v1, v2_i, v3)))
## # A tibble: 12 x 9
## # Rowwise:
## subj gender age grp v1 v2 v3 v2_i v_mean
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 84 33.7
## 2 2 f 33 2 67 73 66 27 53.3
## 3 3 f 47 3 86 87 91 13 63.3
## 4 4 f 10 1 64 68 67 32 54.3
## 5 5 f 21 2 40 46 44 54 46
## 6 6 f 30 3 26 34 28 66 40
## 7 7 m 51 1 64 66 64 34 54
## 8 8 m 13 2 61 66 64 34 53
## 9 9 m 17 3 67 67 67 33 55.7
## 10 10 m 25 1 38 36 35 64 45.7
## 11 11 m 33 2 22 25 21 75 39.3
## 12 12 m 27 3 81 86 81 14 58.7
# rowwise means seems to work only using unquoted column names
# unquoted column names need to be combined c()
# without inversion we could even use the : operator when variables are one aside the other
dplyr::rowwise(dd) %>% dplyr::mutate(v_mean = mean(c(v1:v3)))
## # A tibble: 12 x 8
## # Rowwise:
## subj gender age grp v1 v2 v3 v_mean
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 8.5
## 2 2 f 33 2 67 73 66 66.5
## 3 3 f 47 3 86 87 91 88.5
## 4 4 f 10 1 64 68 67 65.5
## 5 5 f 21 2 40 46 44 42
## 6 6 f 30 3 26 34 28 27
## 7 7 m 51 1 64 66 64 64
## 8 8 m 13 2 61 66 64 62.5
## 9 9 m 17 3 67 67 67 67
## 10 10 m 25 1 38 36 35 36.5
## 11 11 m 33 2 22 25 21 21.5
## 12 12 m 27 3 81 86 81 81
# we might even use some function outside of dplyr commands with piping: here rowMeans
dd %>% dplyr::mutate(v2_i = 100 - v2) %>% dplyr::select(v1, v2_i, v3) %>% dplyr::rowwise() %>% rowMeans()
## [1] 33.66667 53.33333 63.33333 54.33333 46.00000 40.00000 54.00000 53.00000
## [9] 55.66667 45.66667 39.33333 58.66667
# as rowMeans already works rowwise, we don't need rowwise when using with rowMeans()
# so we get the same doing
dd %>% dplyr::mutate(v2_i = 100 - v2) %>% dplyr::select(v1, v2_i, v3) %>% rowMeans()
## [1] 33.66667 53.33333 63.33333 54.33333 46.00000 40.00000 54.00000 53.00000
## [9] 55.66667 45.66667 39.33333 58.66667
# we might even define our own function and apply it to each row
# we define a function that returns the mean of a vector of values excluding the lowest one
mean_c <- function(x){return (mean(x[order(x)[2:length(x)]]))}
# just to see what mean_c does: this should return 6, the mean of 8 and 4, 2 is excluded
mean_c(c(8,4,2))
## [1] 6
# we want to have the mean of v1, v2, and v3, excluding the minimum value of the three. this should be done for each observation.
dplyr::rowwise(dd) %>% dplyr::mutate(v_mean_c = mean_c(c(v1, v2, v3)))
## # A tibble: 12 x 8
## # Rowwise:
## subj gender age grp v1 v2 v3 v_mean_c
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 12.5
## 2 2 f 33 2 67 73 66 70
## 3 3 f 47 3 86 87 91 89
## 4 4 f 10 1 64 68 67 67.5
## 5 5 f 21 2 40 46 44 45
## 6 6 f 30 3 26 34 28 31
## 7 7 m 51 1 64 66 64 65
## 8 8 m 13 2 61 66 64 65
## 9 9 m 17 3 67 67 67 67
## 10 10 m 25 1 38 36 35 37
## 11 11 m 33 2 22 25 21 23.5
## 12 12 m 27 3 81 86 81 83.5
Die dplyr-Kommandos haben inzwischen eine Variante bekommen, die die jeweilige Manipulation nur auf Teile der Daten beschränkt. Dies hat den Vorteil, dass der Rest der Daten unverändert “mitgenommen” wird und am Ende gespeichert werden können.
Ein paar Beispiele
require(tidyverse)
dd <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# todo ...
We can summarize over observations, defined by group_by()
. Then we have one summarized value per subgroup. This can be saved in a collapsed manner. Alternatively the summarized value can be stored in a new column for all observations. All members of a subgroup as defined by group_by()
then share the same summarized value.
require(tidyverse)
dd <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
dd %>% dplyr::group_by(grp) %>% dplyr::mutate(av.v1 = mean(v1, na.rm = TRUE))
## # A tibble: 12 x 8
## # Groups: grp [3]
## subj gender age grp v1 v2 v3 av.v1
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 43.8
## 2 2 f 33 2 67 73 66 47.5
## 3 3 f 47 3 86 87 91 65
## 4 4 f 10 1 64 68 67 43.8
## 5 5 f 21 2 40 46 44 47.5
## 6 6 f 30 3 26 34 28 65
## 7 7 m 51 1 64 66 64 43.8
## 8 8 m 13 2 61 66 64 47.5
## 9 9 m 17 3 67 67 67 65
## 10 10 m 25 1 38 36 35 43.8
## 11 11 m 33 2 22 25 21 47.5
## 12 12 m 27 3 81 86 81 65
dd %>% dplyr::group_by(gender) %>% dplyr::mutate(av.v1 = mean(v1, na.rm = TRUE))
## # A tibble: 12 x 8
## # Groups: gender [2]
## subj gender age grp v1 v2 v3 av.v1
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 48.7
## 2 2 f 33 2 67 73 66 48.7
## 3 3 f 47 3 86 87 91 48.7
## 4 4 f 10 1 64 68 67 48.7
## 5 5 f 21 2 40 46 44 48.7
## 6 6 f 30 3 26 34 28 48.7
## 7 7 m 51 1 64 66 64 55.5
## 8 8 m 13 2 61 66 64 55.5
## 9 9 m 17 3 67 67 67 55.5
## 10 10 m 25 1 38 36 35 55.5
## 11 11 m 33 2 22 25 21 55.5
## 12 12 m 27 3 81 86 81 55.5
# dealing with serveral modifications
dd %>% dplyr::group_by(gender) %>% dplyr::summarise(av.v1 = mean(v1, na.rm = TRUE), av.v2 = mean(v2, na.rm = TRUE)) # summarise collapses
## # A tibble: 2 x 3
## gender av.v1 av.v2
## <chr> <dbl> <dbl>
## 1 f 48.7 54
## 2 m 55.5 57.7
dd %>% dplyr::group_by(gender) %>% dplyr::mutate(av.v1 = mean(v1, na.rm = TRUE), av.v2 = mean(v2, na.rm = TRUE)) # mutate aggregates only and keeps the observations
## # A tibble: 12 x 9
## # Groups: gender [2]
## subj gender age grp v1 v2 v3 av.v1 av.v2
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 48.7 54
## 2 2 f 33 2 67 73 66 48.7 54
## 3 3 f 47 3 86 87 91 48.7 54
## 4 4 f 10 1 64 68 67 48.7 54
## 5 5 f 21 2 40 46 44 48.7 54
## 6 6 f 30 3 26 34 28 48.7 54
## 7 7 m 51 1 64 66 64 55.5 57.7
## 8 8 m 13 2 61 66 64 55.5 57.7
## 9 9 m 17 3 67 67 67 55.5 57.7
## 10 10 m 25 1 38 36 35 55.5 57.7
## 11 11 m 33 2 22 25 21 55.5 57.7
## 12 12 m 27 3 81 86 81 55.5 57.7
# multiple grouping is possible
dd %>% dplyr::group_by(gender, grp) %>% dplyr::summarize(av.v1 = mean(v1, na.rm = TRUE))
## `summarise()` has grouped output by 'gender'. You can override using the `.groups` argument.
## # A tibble: 6 x 3
## # Groups: gender [2]
## gender grp av.v1
## <chr> <dbl> <dbl>
## 1 f 1 36.5
## 2 f 2 53.5
## 3 f 3 56
## 4 m 1 51
## 5 m 2 41.5
## 6 m 3 74
dd %>% dplyr::group_by(gender, grp) %>% dplyr::mutate(av.v1 = mean(v1, na.rm = TRUE))
## # A tibble: 12 x 8
## # Groups: gender, grp [6]
## subj gender age grp v1 v2 v3 av.v1
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 36.5
## 2 2 f 33 2 67 73 66 53.5
## 3 3 f 47 3 86 87 91 56
## 4 4 f 10 1 64 68 67 36.5
## 5 5 f 21 2 40 46 44 53.5
## 6 6 f 30 3 26 34 28 56
## 7 7 m 51 1 64 66 64 51
## 8 8 m 13 2 61 66 64 41.5
## 9 9 m 17 3 67 67 67 74
## 10 10 m 25 1 38 36 35 51
## 11 11 m 33 2 22 25 21 41.5
## 12 12 m 27 3 81 86 81 74
dd %>% group_by(gender, grp) %>% dplyr::mutate(av.v1 = mean(v1, na.rm = TRUE, av.v2 = mean(v2, na.rm = TRUE)))
## # A tibble: 12 x 8
## # Groups: gender, grp [6]
## subj gender age grp v1 v2 v3 av.v1
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 f 17 1 9 16 8 36.5
## 2 2 f 33 2 67 73 66 53.5
## 3 3 f 47 3 86 87 91 56
## 4 4 f 10 1 64 68 67 36.5
## 5 5 f 21 2 40 46 44 53.5
## 6 6 f 30 3 26 34 28 56
## 7 7 m 51 1 64 66 64 51
## 8 8 m 13 2 61 66 64 41.5
## 9 9 m 17 3 67 67 67 74
## 10 10 m 25 1 38 36 35 51
## 11 11 m 33 2 22 25 21 41.5
## 12 12 m 27 3 81 86 81 74
Um einen Teil der Zeilen einer Spalte zu überschreiben, z. B. subgruppenspezifisch, können wir ifelse()
verwenden und den veränderten DataFrame zurückspeichern.
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# is there a gender difference in
df %>% dplyr::group_by(gender) %>% dplyr::summarise(mean(v1), mean(v2), mean(v3))
## # A tibble: 2 x 4
## gender `mean(v1)` `mean(v2)` `mean(v3)`
## <chr> <dbl> <dbl> <dbl>
## 1 f 48.7 54 50.7
## 2 m 55.5 57.7 55.3
t.test(v1 ~ gender, data=df)
##
## Welch Two Sample t-test
##
## data: v1 by gender
## t = -0.46636, df = 9.2652, p-value = 0.6517
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -39.83543 26.16876
## sample estimates:
## mean in group f mean in group m
## 48.66667 55.50000
# lower v1 values of men in place
df %>% mutate(v1 = ifelse(gender == "m", v1 - 7, v1)) -> df
t.test(v1 ~ gender, data=df)
##
## Welch Two Sample t-test
##
## data: v1 by gender
## t = 0.011375, df = 9.2652, p-value = 0.9912
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -32.83543 33.16876
## sample estimates:
## mean in group f mean in group m
## 48.66667 48.50000
mit case_when()
require(tidyverse)
df <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
# require(dplyr)
# is there a gender difference in
df %>% dplyr::group_by(gender) %>% dplyr::summarise(mean(v1), mean(v2), mean(v3))
## # A tibble: 2 x 4
## gender `mean(v1)` `mean(v2)` `mean(v3)`
## <chr> <dbl> <dbl> <dbl>
## 1 f 48.7 54 50.7
## 2 m 55.5 57.7 55.3
t.test(v1 ~ gender, data=df)
##
## Welch Two Sample t-test
##
## data: v1 by gender
## t = -0.46636, df = 9.2652, p-value = 0.6517
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -39.83543 26.16876
## sample estimates:
## mean in group f mean in group m
## 48.66667 55.50000
# lower v1 values of men in place
df %>% dplyr::mutate(v1 = as.double(v1)) %>%
dplyr::mutate(vn = dplyr::case_when(gender == 'm' ~ v1 - 7,
gender == 'f' ~ v1,
TRUE ~ NA_real_)) -> df
t.test(vn ~ gender, data=df)
##
## Welch Two Sample t-test
##
## data: vn by gender
## t = 0.011375, df = 9.2652, p-value = 0.9912
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -32.83543 33.16876
## sample estimates:
## mean in group f mean in group m
## 48.66667 48.50000
We can use dplyr
to control statistical models and use model properties to do some data modification. Here we take out a gender level difference.
# is there a gender difference
dd <- readr::read_tsv("https://md.psych.bio.uni-goettingen.de/mv/data/div/df_dplyr.txt")
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## subj = col_double(),
## gender = col_character(),
## age = col_double(),
## grp = col_double(),
## v1 = col_double(),
## v2 = col_double(),
## v3 = col_double()
## )
dd %>% dplyr::group_by(gender) %>% dplyr::summarise(mean(v1), mean(v2), mean(v3))
## # A tibble: 2 x 4
## gender `mean(v1)` `mean(v2)` `mean(v3)`
## <chr> <dbl> <dbl> <dbl>
## 1 f 48.7 54 50.7
## 2 m 55.5 57.7 55.3
(tt <- t.test(v1 ~ gender, data=dd))
##
## Welch Two Sample t-test
##
## data: v1 by gender
## t = -0.46636, df = 9.2652, p-value = 0.6517
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -39.83543 26.16876
## sample estimates:
## mean in group f mean in group m
## 48.66667 55.50000
gender_diff <- tt[['estimate']][2] - tt[['estimate']][1]
# let's take out the gender difference by lowerin mens v1 values in place and store it back to the data object
dd %>% dplyr::mutate(v1 = as.double(v1)) %>%
dplyr::mutate(vn = dplyr::case_when(gender == 'm' ~ v1 - gender_diff,
gender == 'f' ~ v1,
TRUE ~ NA_real_)) -> dd
# the difference should have disappeared
t.test(vn ~ gender, data=dd)
##
## Welch Two Sample t-test
##
## data: vn by gender
## t = 0, df = 9.2652, p-value = 1
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -33.00209 33.00209
## sample estimates:
## mean in group f mean in group m
## 48.66667 48.66667
Im Datensatz Big5_GEMI_R_recoded.csv finden sich die Daten von 160 Vpn. Von allen haben wir das Alter, das Geschlecht (0=Frau, 1=Mann) sowie 60 NEO-FFI Items. Die zu invertierenden Items sind bereits umkodiert. Die entsprechenden Variablennamen enden auf "_rec" (z. B. neo_ffi_8_rec, neo_ffi_9_rec).
Die Skala Extraversion setzt sich zusammen aus den Variablen:
neo_ffi_2, neo_ffi_7, neo_ffi_12_rec, neo_ffi_17, neo_ffi_22, neo_ffi_27_rec, neo_ffi_32, neo_ffi_37, neo_ffi_42_rec, neo_ffi_47, neo_ffi_52, neo_ffi_57_rec
Wir brauchen einen temporären Dataframe “data_e_t”, der nur die Extraversionsitems enthält
Erstelle einen Dataframe “data_e”, der das Geschlecht, das Alter sowie die Extraversionsitems enthält.
Bilde eine Variable mit Namen “neo_e”, in der der Mittelwert aus den Extraversions-Items gebildet wird und an den Dataframe data_e angehängt wird.
Gebe aus “data_e” Alter, Geschlecht und die Skalenwerte “neo_e” aller Frauen (vpsex hat Wert 0) aus, die über 24 Jahre alt sind.
Gebe aus “data_e” den Mittelwert von “neo_e” aus, getrennt nach Geschlecht. Normalerweise haben Frauen etwas höhere Extraversions-Werte wie Männer.
require(tidyverse)
data <- read.csv2('http://e-scientifics.de/content/datasets/Big5_GEMI_R_recoded.csv') # read data, items already recoded
# require(dplyr)
# solution 1.
data_e_t <- dplyr::select(data, neo_ffi_2, neo_ffi_7, neo_ffi_12_rec, neo_ffi_17, neo_ffi_22, neo_ffi_27_rec, neo_ffi_32, neo_ffi_37, neo_ffi_42_rec, neo_ffi_47, neo_ffi_52, neo_ffi_57_rec)
# take a look at it
head(dplyr::select(data_e_t, neo_ffi_2:neo_ffi_22))
## neo_ffi_2 neo_ffi_7 neo_ffi_12_rec neo_ffi_17 neo_ffi_22
## 1 1 1 2 1 1
## 2 1 0 1 2 1
## 3 -1 1 1 2 -1
## 4 2 1 2 1 0
## 5 1 2 2 2 0
## 6 1 2 2 2 0
# and delete this temporary dataframe
rm(data_e_t)
# solution 2.
data_e <- dplyr::select(data, vpsex, vpage, neo_ffi_2, neo_ffi_7, neo_ffi_12_rec, neo_ffi_17, neo_ffi_22, neo_ffi_27_rec, neo_ffi_32, neo_ffi_37, neo_ffi_42_rec, neo_ffi_47, neo_ffi_52, neo_ffi_57_rec)
# solution 3.
data_e <- dplyr::rowwise(data_e) %>% dplyr::mutate(neo_e = mean(c(neo_ffi_2, neo_ffi_7, neo_ffi_12_rec, neo_ffi_17, neo_ffi_22, neo_ffi_27_rec, neo_ffi_32, neo_ffi_37, neo_ffi_42_rec, neo_ffi_47, neo_ffi_52, neo_ffi_57_rec)))
# solution 4.
dplyr::filter(data_e, vpage > 24, vpsex == 0) %>% dplyr::select(vpsex, vpage, neo_e)
## # A tibble: 17 x 3
## # Rowwise:
## vpsex vpage neo_e
## <int> <int> <dbl>
## 1 0 32 0.417
## 2 0 28 0.583
## 3 0 26 1
## 4 0 27 1
## 5 0 46 0.833
## 6 0 26 1.08
## 7 0 25 0.417
## 8 0 25 0.583
## 9 0 45 -0.167
## 10 0 27 1.25
## 11 0 26 0.333
## 12 0 25 0.417
## 13 0 28 0.0833
## 14 0 27 -0.5
## 15 0 25 0.667
## 16 0 29 0.667
## 17 0 25 0.0833
# solution 5.
dplyr::group_by(data_e, vpsex) %>% dplyr::summarise(mean(c(neo_e)))
## # A tibble: 2 x 2
## vpsex `mean(c(neo_e))`
## <int> <dbl>
## 1 0 0.521
## 2 1 0.456
dplyr hat einen weit über diese Einführung hinausgehenden Befehlsumfang. Beispielsweise gibt es eine ganze Familie von Befehlen, die Ideen aus dem Umfeld von relationalen Datenbanken auf die statistische Datenaufbereitung überträgt. Dies spielt eine Rolle beim Zusammenbauen von verschiedenen Datentabellen zu einer neuen (data merging).
Ein paar Beispiele finden sich in dplyr_advanced
Zum Vergleich Datenmodifikation mit dem Base-System vs. Datenmodifikation mit dplyr gibt es ein vergleichendes Beispiel panas_base vs. panas_dplyr
Body Comparison (PACS) als html
Befehlsreferenz mit Beispielen
http://rpubs.com/justmarkham/dplyr-tutorial
http://www.r-bloggers.com/hands-on-dplyr-tutorial-for-faster-data-manipulation-in-r/
Hadley Wickhams Artikel zu tidy data, auch lokal.
.var und .fun example
Datenmodifikation von Einzelspalten und Zurückschreiben in Tibble (Johannes’ Übungen) Erreichbar durch die Anwendung der neueren …_at() Befehle.
mydata2 %>% mutate(species_new = case_when(is.na(Species) ~ "missing",
Species=="setosa" ~ "setosa_new",
Species=="versicolor" ~ "versicolor_new",
Species=="virginica" ~ "virginica_new",
TRUE ~ "others"))
df1 = mydata2 %>%
rowwise() %>% mutate(row_max= max(Sepal.Length:Petal.Width))
head(df1)
percentile rank http://www.datasciencemadesimple.com/calculate-percentile-quantile-n-tile-of-dataframe-in-r-using-dplyr-create-column-with-percentile-rank/
glimpse()
todo: # using case_when
x=read.table(text="V1 V2 V3 V4
1 1 2 3 5
2 2 4 4 1
3 1 4 1 1
4 4 5 1 3
5 5 5 5 4",
col.names=c("V1", "V2", "V3", "V4"))
x$V5 = case_when(m$V1==1 & x$V2!=4 ~ 1,
x$V2==4 & x$V3!=1 ~ 2,
TRUE ~ 0)
dd$pho_sem2 = case_when(dd$condition == "Pho_Con" | dd$condition == "Pho_Exp" ~ "pho",
dd$condition == "PhoSem_Con" | dd$condition == "PhoSem_Exp" ~ "sem")
dd$exp_con2 = case_when(dd$condition == "Pho_Con" | dd$condition == "PhoSem_Con" ~ "con",
dd$condition == "Pho_Exp" | dd$condition == "PhoSem_Exp" ~ "exp")
Version: 11 April, 2021 13:54