Ein Tutorial zum Selbststudium von Johannes Gerwien, unter Mitarbeit von Franziska Arnold und Tamaki Ogura
Sie wollen lernen, wie Sie mit Hilfe des Statistik-Programms R Daten auswerten können? Sie haben aber gehört, dass man für die Arbeit mit R Programmierkenntnisse braucht, haben bisher aber überhaupt keine Erfahrung mit Programmieren?
Dann sind Sie hier genau richtig! Sie lernen in diesem Tutorial Schritt für Schritt die Grundlagen für das Programmieren mit R.
Unser Fokus liegt dabei auf dem Umgang mit R Studio. An vielen Stellen haben wir Informationen zum mathematischen Hintergrund der Berechnungen in diesem Tutorial verlinkt.
Kapitelübersicht
In diesem Kapitel lernen Sie die Programmiersprache R kennen. Bevor es aber richtig losgeht, müssen Sie sich R und R Studio installieren. Wie das geht, erfahren Sie in einem der nächsten Abschnitte. Außerdem gibt es am Ende dieses Kapitels eine Übersicht “Programmier-Slang”, die Begriffe enthält, die Ihnen später in diesem Tutorial immer wieder begegnen werden.
Wie wir aus unserem Alltagsleben wissen, kann ein Computer heutzutage ziemlich viel: z.B. Infos aus dem Internet anzeigen, Fotos bearbeiten, eine Präsentation erstellen usw. Aber haben Sie sich schon mal Gedanken darüber gemacht, wie das funktioniert? Dem Computer wurde zu irgendeinem Zeitpunkt genau gesagt, was zu tun ist, genauer gesagt, ein Computer wurde für die Erledigung jeder einzelnen Aufgabe programmiert. Mit R tun wir genau das. Wir programmieren den Computer darauf, eine ganz bestimmte statistische Analyse durchzuführen. Dafür benutzen wir die Programmiersprache R. Aber keine Sorge, die Verwendung von R ist viel einfacher als Sie denken!
Computer beherrschen in der Regel viele verschiedene Programmiersprachen. Interessant ist dabei, dass jede Programmiersprache aus Vokabeln und einer Grammatik besteht, fast wie eine natürliche Sprache. Nach einer kurzen Vorbereitung schauen wir uns das gleich etwas genauer an.
R Studio ist ein Arbeitsplatz speziell für die Verwendung der Programmiersprache R. Dabei stellt R Studio ein paar wichtige Vorteile bereit: Die Vorbereitung der Datenanalyse, die eigentliche Ausführung der Analyse und die Ergebnisse der Analyse werden in verschiedenen Fenstern dargestellt, so dass man nicht zwischen verschiedenen Programmen hin- und herwechseln muss. Darüber hinaus gibt es viele kleine Hilfsfunktionen, die die Arbeit mit der Programmiersprache R extrem vereinfachen.
Sie müssen zwei Dinge installieren (am besten in der unten angegebenen Reihenfolge):
Die Benutzeroberfläche ist in vier Bereiche aufgeteilt. Die Anordnung und Sichtbarkeit dieser Bereiche können vollständig selbst gesteuert werden. Wir schauen uns jetzt zunächst die Benutzeroberfläche unter der Standardeinstellung an.
Im Editorfenster (1) gibt man Kommandos bzw. Code ein. Wir verwenden die Begriffe Kommando und Code synonym. Kommandos können in einem Skript zusammengefasst werden. Kommandos werden an die Konsole geschickt und dort ausgeführt. Wenn Sie jetzt schon wissen wollen, was genau mit diesen Begriffen gemeint ist, schauen Sie in diesem Kapitel im Abschnitt “Programmier-Slang” nach.
Warum? In R Studio sind die Arbeitsplätze, in denen man Skripts vorbereitet (1), ausführt (2) und die Ergebnisse ausgegeben werden (2, 3, 4), getrennt. Dadurch wird es möglich:
Wie oben beschrieben, ist die Konsole, der Ort, an dem die Kommandos ausgeführt und die Ergebnisse angezeigt werden.
Zwar kann man Code auch direkt in die Konsole eingeben und ausführen, aber wir empfehlen, Kommandos in einem Skript vorzubereiten und dann an die Konsole zu schicken. Ein Skript sollte man abspeichern, damit Code später reproduziert bzw. überprüft werden kann. Dies ist wichtig, da alles, was in der Konsole eingegeben und ausgegeben wurde, gelöscht wird, wenn man R Studio einmal schließt.
Die größte Stärke von R besteht in der “Manipulation” von (geladenen) Daten. Mit R ist es viel einfacher als zum Beispiel mit Excel, Daten in Subsets zu strukturieren, Daten zu ordnen, oder Daten in anderer Weise für die Analyse zu verändern
Dabei gilt Folgendes:
objekt <- "mein erstes Objekt" # Objekt erstellen
objekt # Objekt ansehen
## [1] "mein erstes Objekt"
Ordnerstruktur von Projekten
Objekte im Environment löschen
# erstmal ein paar Objekte erstellen
objekt <- "x"
objekt1 <- "y"
objekt2 <- "z"
a <- "oh"
b <- "nein"
ls() # alle Objekte anzeigen
## [1] "a" "b" "objekt" "objekt1" "objekt2"
# Jetzt wieder löschen
rm(objekt) # damit löscht man ein Objekt
rm(objekt1,objekt2) # mehrere Objekte
rm(list=setdiff(ls(), c("a", "c"))) # alle Objekte außer "a" und "b"
rm(list = ls()) # wirklich alle Objekte
ls() # alle Objekte anzeigen
## character(0)
In R Studio stehen in der Basisinstallation bereits viele Funktionen automatisch zur Verfügung, die Ihnen bei Datenanalyse helfen. In diesem Tutorial werden wir aber teilweise erweiterte Funktionen verwenden. Solche erweiterten Funktionen sind in sogenannten Paketen (“packages”/“libraries”) verfügbar.
library(base) # ein bereits installiertes Paket laden
Das Aktivieren eines Pakets setzt aber voraus, dass das zu verwendende Paket auch verfügbar ist. Sollte ein Paket nicht verfügbar sein, dann müssen Sie es einmalig herunterladen und installieren.
library(plyr) # versuchen, ein noch nicht installiertes Paket zu laden; in diesem Fall "plyr"
if(!require(readr)){install.packages("readr")} # checken, ob "readr" vorhanden ist, wenn nicht, dann installieren, wenn vorhanden, dann laden
## Loading required package: readr
Wir fassen nochmal alle wichtigen grundlegenden Begriffe zusammen und stellen einige neue vor, die im Weiteren wichtig sind. Bitte überspringen Sie diesen Abschnitt nicht!
Kommando:
Script:
Paket:
Objekt:
Zuweisung:
objekt <- 1+1+1+1
Vektor:
vector <- c(1, 3, 5, 7)
(Mac) "~/Users/username/Desktop/Tutorial/raw data/"
(Windows) "C:/Users/username/Desktop/Tutorial/raw data"
relative Pfade
(Mac relativer Pfad): "./raw data/" # Pfad zum Ordner raw data im aktuellen Projekt
(Windows relativer Pfad) "./raw data/" # Pfad zum Ordner raw data im aktuellen Projekt
In diesem Tutorial werden immer relative Pfade angegeben, weil wir natürlich nicht wissen, wo Sie Ihr R-Tutorial auf Ihrem Computer abspeichern
Dies ist auch der Grund, warum wir noch einmal ausdrücklich empfehlen, die oben beschriebene Ordnerstruktur zu verwenden
Kommentar:
# weist dem Objekt "vector" die Werte 1, 3, 5, 7 zu
vector <- c(1, 3, 5, 7) # weist dem Objekt "vector" die Werte 1, 3, 5, 7 zu
# weist dem Objekt "vector" die Werte 1, 3, 5, 7 zu
Kapitelübersicht
In diesem Kapitel werden Sie lernen, wie man Datentabellen in RStudio öffnet, was bei unterschiedlichen Datentypen zu beachten ist und wie man neue Datensätze erstellt und verändert.
Daten runterladen
Wir verwenden in diesem Kapitel und im nächsten Kapitel ein paar Testdaten. Laden Sie bitte die folgenden Dateien:
hier runter und legen Sie die beiden Dateien im Ordner “raw data” ab.
Ordnerstruktur überprüfen
Wir gehen im Folgenden davon aus, dass Sie mit der in Kapitel 1 vorbereiteten Ordnerstruktur weiterarbeiten.
pseudo_et_data <- read.csv("./raw data/pseudo_et_data.csv", sep=";")
write.csv2(pseudo_et_data, file = "./processed data/proc_data.csv")
data(iris) #Laden des R internen df "iris"
head(iris) #Anzeigen der ersten 5 Zeilen
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
str(iris) #Struktur von df "iris"
## 'data.frame': 150 obs. of 5 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
test_1 <- c("A","B","C") # der Vektor enthält Daten des Typs character
test_1
## [1] "A" "B" "C"
test_2 <- c(1, 2, 3) # der Vektor enthält Daten des Typs numeric
test_2
## [1] 1 2 3
# versuchen wir mal ohne "" auf character oder factor - Daten zuzugreifen; löschen Sie "#" vor dem nächsten Code-Schnipsel
# test_3 <- c(X,Y,Z) # ohne "" weiß R nicht, was die Buchstaben bedeuten sollen
# test_3
# es erscheint eine Fehlermeldung
head(pseudo_et_data)
## index sub tot.dur hits AOI condition
## 1 1 Steven 892 5 circle C
## 2 2 Steven 154 2 triangle B
## 3 3 Steven 712 3 square B
## 4 4 Steven 346 4 square A
## 5 5 Steven 179 4 circle C
## 6 6 Steven 50 3 triangle C
str(pseudo_et_data)
## 'data.frame': 140 obs. of 6 variables:
## $ index : int 1 2 3 4 5 6 7 8 9 10 ...
## $ sub : chr "Steven" "Steven" "Steven" "Steven" ...
## $ tot.dur : int 892 154 712 346 179 50 399 642 348 899 ...
## $ hits : int 5 2 3 4 4 3 2 5 5 4 ...
## $ AOI : chr "circle" "triangle" "square" "square" ...
## $ condition: chr "C" "B" "B" "A" ...
one <- c(1,2,3,4,5) # it’s a vector
two <- c("A","B","C","D","E") # it’s another vector
A <- data.frame(one,two) # let’s combine them in a df
A # Name des df als Kommando in der Konsole
## one two
## 1 1 A
## 2 2 B
## 3 3 C
## 4 4 D
## 5 5 E
head(A, n = 3) # head mit Angabe der "n" zeigt nur den Anfang eines df; n erlaubt jede beliebige Zahl
## one two
## 1 1 A
## 2 2 B
## 3 3 C
tail(A, n = 2 ) # tail mit Angabe der "n" zeigt nur das Ende eines df; die Logik ist dieselbe wie bei head
## one two
## 4 4 D
## 5 5 E
colnames(A) <- c("good", "better") # let’s change the column names
head(A, n = 2 )
## good better
## 1 1 A
## 2 2 B
rm(one, two)
three <- c(1,0,0,0,1) # ein weiterer Vektor
A <- cbind(A, three) # hänge den neuen Vektor an den existierenden df
A.new <- A # Kopie des df "A" erstellen
A.new <- cbind(A, three) # das hätten wir auch anders lösen können
head(A.new, n = 2 ) # überprüfen
## good better three three
## 1 1 A 1 1
## 2 2 B 0 0
rm(A) # löschen des df A
A.new[1,1] # erste Zeile, erste Spalte
## [1] 1
A.new[1,2] # erste Zeile, zweite Spalte
## [1] "A"
A.new[5,2] # fünfte Zeile, zweite Spalte
## [1] "E"
A.new[ ,2] # alle Werte in der zweiten Spalte
## [1] "A" "B" "C" "D" "E"
A.new[2, ] # alle Werte in der zweiten Zeile
## good better three three
## 2 2 B 0 0
vektor_x <- A.new[ ,4] # alle Werte in der zweiten Spalte im Vektor "vektor_x" speichern
vektor_x # Vektor ansehen
## [1] 1 0 0 0 1
rm(vektor_x) # aber eigentlich brauchen wir ihn nicht, daher löschen
head(A.new) # zuerst nochmal den df angucken
## good better three three
## 1 1 A 1 1
## 2 2 B 0 0
## 3 3 C 0 0
## 4 4 D 0 0
## 5 5 E 1 1
A.new[, 4] <- NULL # jetzt die vierte Spalte mit 'NULL' löschen
head(A.new) # Ergebnis überprüfen
## good better three
## 1 1 A 1
## 2 2 B 0
## 3 3 C 0
## 4 4 D 0
## 5 5 E 1
colnames(A.new)[3] <- "perfect" # Namen der dritten Spalte ändern
head(A.new) # Ergebnis überprüfen
## good better perfect
## 1 1 A 1
## 2 2 B 0
## 3 3 C 0
## 4 4 D 0
## 5 5 E 1
colnames(A.new)[c(1,3)] <- c("cool","ok") # Namen der ersten und dritten Spalte ändern
head(A.new) # Ergebnis überprüfen
## cool better ok
## 1 1 A 1
## 2 2 B 0
## 3 3 C 0
## 4 4 D 0
## 5 5 E 1
A.new$ok
## [1] 1 0 0 0 1
A.new[2,"ok"] # Alternative zu A.new[2,3]; der Name der dritten Spalte ist "ok"
## [1] 0
# zuerst schauen wir, wie viele verschiedene Typen es in der Kategorie "cyl" (Zylinder) überhaupt gibt; wir benutzen "unique"
unique(mtcars$cyl)
## [1] 6 4 8
my_first_subset <- mtcars[mtcars$cyl == 4, ] # erstelle Objekt, das aus Daten des Datensatzes "mtcars" besteht, und benutze Zeilen, bei denen in der Spalte "cyl" eine 4 steht
head(my_first_subset,5)
## mpg cyl disp hp drat wt qsec vs am gear carb
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
my_second_subset <- mtcars[mtcars$cyl != 4, ] # erstelle Objekt, das aus Daten des Datensatzes "mtcars" besteht, und benutze Zeilen, bei denen in der Spalte "cyl" keine 4 steht
#view(my_second_subset)
unique(my_second_subset$cyl)
## [1] 6 8
my_third_subset <- mtcars[mtcars$cyl > 4 & mtcars$cyl < 8, ] # erstelle Objekt, das aus Daten des Datensatzes "mtcars" besteht, und benutze Zeilen, bei denen in der Spalte "cyl" Werte größer 4, aber kleiner 8 stehen
unique(my_third_subset$cyl) # wir überprüfen das Ergebnis
## [1] 6
#view(my_third_subset) #schauen Sie sich auch wieder das Objekt in R an (# löschen, bevor Sie den Befehl ausführen)
my_fourth_subset <- mtcars[mtcars$cyl == 6 | mtcars$cyl == 8, ] # erstelle Objekt, das aus Daten des Datensatzes "mtcars" besteht, und benutze Zeilen, bei denen in der Spalte "cyl" die Werte 6 oder 8 zu finden sind
unique(my_fourth_subset$cyl) # wir überprüfen das Ergebnis
## [1] 6 8
#view(my_fourth_subset) #schauen Sie sich auch wieder das Objekt in R an (# löschen, bevor Sie den Befehl ausführen)
# erstelle ein Subset aus dem Dataframe data, bei dem in der Spalte "column" die Werte "Wert1", "Wert2", etc. zu finden sind
subset <- data[(data$column %in% c("Wert1", "Wert2","Wert3","Wert4")), ]
# erstelle ein Subset aus dem Dataframe data, bei dem in der Spalte "column" NICHT die Werte "Wert1", "Wert2", etc zu finden sind - Ausrufezeichen beachten!
subset <- data[!(data$column %in% c("Wert1", "Wert2","Wert3","Wert4")), ]
# erzeuge einen Vektor "s" mit den Zahlen von 1 bis 140
s <- seq(1, 140, 1)
# erzeuge einen Vektor mit dem Wort "Liste1", das 140 Mal wiederholt wird
t1 <- rep("Liste1",140)
# erzeuge ein Objekt mit Namen "add_info", das ein Dataframe ist, in dem die beiden Vektoren "s" und "t1" als Spalten enthalten sind
add_info <- as.data.frame(cbind(s,t1))
# Benenne die Spalten des Dataframe "add_info" um, und zwar in "index" und "Liste
colnames(add_info) <- c("index","Liste")
head(add_info)
## index Liste
## 1 1 Liste1
## 2 2 Liste1
## 3 3 Liste1
## 4 4 Liste1
## 5 5 Liste1
## 6 6 Liste1
d <- pseudo_et_data # wir erstellen eine Kopie von pseudo_et_data
# zuerst sicherstellen, dass die Spalte, in der gesucht und ersetzt werden soll, Daten des Typs "Character" enthält
library(plyr)
unique(d$sub) # Überprüfen, was für Werte sich in der Spalte "sub" befinden
## [1] "Steven" "Katharina" "Alice" "bruno" "Tinker Bell"
## [6] "Ben" "Eduard"
d <- pseudo_et_data # wir erstellen eine Kopie von pseudo_et_data
d <- mutate(d,sub=as.character(sub))
# jetzt Suche nach "Bell", wenn gefunden, durch "" (nichts) ersetzen (=löschen)
d$sub <- gsub("Bell","",d$sub)
unique(d$sub) # Überprüfen, was sich in Spalte subject_nr geändert hat
## [1] "Steven" "Katharina" "Alice" "bruno" "Tinker " "Ben"
## [7] "Eduard"
library(plyr)
### Infos aus "add_info"" dem objekt "pseudo_et_data" hinzufügen, und zwar an den Stellen, wo es einen match in den Spalten "index" gibt und (wo beide Objekte denselben Wert haben)
d <- join(pseudo_et_data,add_info, by = c("index"), type = "left", match = "first")
str(d)
## 'data.frame': 140 obs. of 7 variables:
## $ index : int 1 2 3 4 5 6 7 8 9 10 ...
## $ sub : chr "Steven" "Steven" "Steven" "Steven" ...
## $ tot.dur : int 892 154 712 346 179 50 399 642 348 899 ...
## $ hits : int 5 2 3 4 4 3 2 5 5 4 ...
## $ AOI : chr "circle" "triangle" "square" "square" ...
## $ condition: chr "C" "B" "B" "A" ...
## $ Liste : chr "Liste1" "Liste1" "Liste1" "Liste1" ...
Teil 1
Im ersten Teil der Übung führen Sie nur den angegebenen Code aus und beobachten, was dadurch geschieht.
Vector1 <- rep(1:9, times = 5)
Vector2 <- rep(1:45)
Vector3 <- rep(c("a", "b", "c"), times = 15)
df1 <- data.frame(Vector1, Vector2, Vector3)
colnames(df1) <- c("count", "rt", "subject")
rm(Vector1)
rm(Vector2)
rm(Vector3)
df1
## count rt subject
## 1 1 1 a
## 2 2 2 b
## 3 3 3 c
## 4 4 4 a
## 5 5 5 b
## 6 6 6 c
## 7 7 7 a
## 8 8 8 b
## 9 9 9 c
## 10 1 10 a
## 11 2 11 b
## 12 3 12 c
## 13 4 13 a
## 14 5 14 b
## 15 6 15 c
## 16 7 16 a
## 17 8 17 b
## 18 9 18 c
## 19 1 19 a
## 20 2 20 b
## 21 3 21 c
## 22 4 22 a
## 23 5 23 b
## 24 6 24 c
## 25 7 25 a
## 26 8 26 b
## 27 9 27 c
## 28 1 28 a
## 29 2 29 b
## 30 3 30 c
## 31 4 31 a
## 32 5 32 b
## 33 6 33 c
## 34 7 34 a
## 35 8 35 b
## 36 9 36 c
## 37 1 37 a
## 38 2 38 b
## 39 3 39 c
## 40 4 40 a
## 41 5 41 b
## 42 6 42 c
## 43 7 43 a
## 44 8 44 b
## 45 9 45 c
Teil 2
df <- pseudo_et_data
AB <- df[df$condition =="A" | df$condition=="B", ]
ABC <- df[df$condition =="A" | df$condition=="B" | df$condition=="C", ]
ABCa <- df[df$condition != "D", ]
BC <- df[df$condition != "A" & df$condition != "D", ]
one <- df[df$sub=="bruno", ]
two <- df[df$sub=="bruno" & df$AOI=="circle", ]
three <- df[df$sub=="bruno" & df$AOI=="circle" & df$condition!="A", ]
four <- head(df[df$sub=="bruno",], n=3)
five <- tail(df[df$sub=="bruno",], n=2)
Teil 3
Teil 4
Kapitelübersicht
In diesem Kapitel lernen Sie erste Schritte, um Ihre Daten zu überprüfen. Darüberhinaus bekommen Sie eine Einführung in für die Datenauswertung wichtige statistische Begriffe.
d <- read.csv("./raw data/pseudo_et_data.csv", sep=";") # wir öffnen das bekannte Datenset pseudo_et_data und nennen es einfach "d"
str(d) #wir schauen uns zunächst an, welche Variablen es gibt
## 'data.frame': 140 obs. of 6 variables:
## $ index : int 1 2 3 4 5 6 7 8 9 10 ...
## $ sub : chr "Steven" "Steven" "Steven" "Steven" ...
## $ tot.dur : int 892 154 712 346 179 50 399 642 348 899 ...
## $ hits : int 5 2 3 4 4 3 2 5 5 4 ...
## $ AOI : chr "circle" "triangle" "square" "square" ...
## $ condition: chr "C" "B" "B" "A" ...
xtabs(~ sub, d) # wie viele Datenzeilen gibt es für jeden einzigarten Wert in der Spalte "sub" ?
## sub
## Alice Ben bruno Eduard Katharina Steven
## 20 20 20 20 20 20
## Tinker Bell
## 20
xtabs(~ AOI, d) # wie viele Datenzeilen gibt es für jeden einzigarten Wert in der Spalte "AOI"?
## AOI
## circle rectangle square triangle
## 49 18 45 28
xtabs(~ condition, d) # wie viele Datenzeilen gibt es für jeden einzigarten Wert in der Spalte "condition"?
## condition
## A B C D
## 36 37 37 30
xtabs(~sub + condition, d)
## condition
## sub A B C D
## Alice 5 5 5 5
## Ben 5 5 5 5
## bruno 5 5 5 5
## Eduard 5 5 5 5
## Katharina 5 5 5 5
## Steven 6 7 7 0
## Tinker Bell 5 5 5 5
xtabs(~ AOI + sub + condition, d)
## , , condition = A
##
## sub
## AOI Alice Ben bruno Eduard Katharina Steven Tinker Bell
## circle 2 4 2 2 4 3 2
## rectangle 0 1 2 1 0 0 0
## square 2 0 0 2 1 2 2
## triangle 1 0 1 0 0 1 1
##
## , , condition = B
##
## sub
## AOI Alice Ben bruno Eduard Katharina Steven Tinker Bell
## circle 1 0 2 1 0 2 1
## rectangle 0 1 1 2 0 0 0
## square 2 4 2 2 1 2 2
## triangle 2 0 0 0 4 3 2
##
## , , condition = C
##
## sub
## AOI Alice Ben bruno Eduard Katharina Steven Tinker Bell
## circle 2 3 1 2 2 3 2
## rectangle 0 2 1 2 0 0 0
## square 1 0 2 1 3 2 1
## triangle 2 0 1 0 0 2 2
##
## , , condition = D
##
## sub
## AOI Alice Ben bruno Eduard Katharina Steven Tinker Bell
## circle 2 0 1 2 1 0 2
## rectangle 0 2 2 1 0 0 0
## square 2 3 0 2 2 0 2
## triangle 1 0 2 0 2 0 1
achten Sie darauf, wie die Daten dargestellt sind: die Variable “condition” gliedert die Darstellung der Ergebnisse; es wird pro Ausprägung angegeben, wie viele Datenzeilen pro sub und pro AOI vorhanden sind
Achtung! die Reihenfolge spielt eine Rolle für die Darstellung der Ergebnisse; vergleichen Sie folgendes mit oben (das Resultat des Befehls ist ausnahmsweise nicht dargestellt):
xtabs(~ AOI + condition + sub, d)
objekt1 <- xtabs(~ sub, d)
objekt1
## sub
## Alice Ben bruno Eduard Katharina Steven
## 20 20 20 20 20 20
## Tinker Bell
## 20
str(objekt1) # Struktur anzeigen lassen
## 'xtabs' int [1:7(1d)] 20 20 20 20 20 20 20
## - attr(*, "dimnames")=List of 1
## ..$ sub: chr [1:7] "Alice" "Ben" "bruno" "Eduard" ...
## - attr(*, "call")= language xtabs(formula = ~sub, data = d)
objekt1 <- as.data.frame(xtabs(~ sub, d))
objekt1
## sub Freq
## 1 Alice 20
## 2 Ben 20
## 3 bruno 20
## 4 Eduard 20
## 5 Katharina 20
## 6 Steven 20
## 7 Tinker Bell 20
str(objekt1) # Struktur anzeigen lassen
## 'data.frame': 7 obs. of 2 variables:
## $ sub : Factor w/ 7 levels "Alice","Ben",..: 1 2 3 4 5 6 7
## $ Freq: int 20 20 20 20 20 20 20
objekt2 <- as.data.frame(xtabs(~ sub + condition, d))
objekt2
## sub condition Freq
## 1 Alice A 5
## 2 Ben A 5
## 3 bruno A 5
## 4 Eduard A 5
## 5 Katharina A 5
## 6 Steven A 6
## 7 Tinker Bell A 5
## 8 Alice B 5
## 9 Ben B 5
## 10 bruno B 5
## 11 Eduard B 5
## 12 Katharina B 5
## 13 Steven B 7
## 14 Tinker Bell B 5
## 15 Alice C 5
## 16 Ben C 5
## 17 bruno C 5
## 18 Eduard C 5
## 19 Katharina C 5
## 20 Steven C 7
## 21 Tinker Bell C 5
## 22 Alice D 5
## 23 Ben D 5
## 24 bruno D 5
## 25 Eduard D 5
## 26 Katharina D 5
## 27 Steven D 0
## 28 Tinker Bell D 5
str(objekt2) # Struktur anzeigen lassen
## 'data.frame': 28 obs. of 3 variables:
## $ sub : Factor w/ 7 levels "Alice","Ben",..: 1 2 3 4 5 6 7 1 2 3 ...
## $ condition: Factor w/ 4 levels "A","B","C","D": 1 1 1 1 1 1 1 2 2 2 ...
## $ Freq : int 5 5 5 5 5 6 5 5 5 5 ...
str(d)
## 'data.frame': 140 obs. of 6 variables:
## $ index : int 1 2 3 4 5 6 7 8 9 10 ...
## $ sub : chr "Steven" "Steven" "Steven" "Steven" ...
## $ tot.dur : int 892 154 712 346 179 50 399 642 348 899 ...
## $ hits : int 5 2 3 4 4 3 2 5 5 4 ...
## $ AOI : chr "circle" "triangle" "square" "square" ...
## $ condition: chr "C" "B" "B" "A" ...
summary(d)
## index sub tot.dur hits
## Min. : 1.00 Length:140 Min. : 14.0 Min. :1.000
## 1st Qu.: 35.75 Class :character 1st Qu.:270.0 1st Qu.:2.000
## Median : 70.50 Mode :character Median :550.0 Median :3.000
## Mean : 70.50 Mean :538.7 Mean :3.036
## 3rd Qu.:105.25 3rd Qu.:829.5 3rd Qu.:4.000
## Max. :140.00 Max. :997.0 Max. :5.000
## AOI condition
## Length:140 Length:140
## Class :character Class :character
## Mode :character Mode :character
##
##
##
boxplot(d$tot.dur, col=c('powderblue'))
boxplot(tot.dur ~ sub, data = d, col=c('powderblue')) # erstelle Boxplots für jede einzelne Ausprägung der Variable sub, und zwar für die Werte der Variable tot.dur
var(d$tot.dur) #Code für die Varianz
## [1] 93624.6
sd(d$tot.dur) #Code für die Standardabweichung
## [1] 305.9814
in der Statistik ist der Begriff der Normalverteilung wichtig; Normalverteilung betrifft die Streuung der Daten; man kann annehmen, dass Daten normalverteilt sind, wenn es viele Datenpunkte gibt, die nah am Median oder Mittelwert liegen und wenige Daten, die weit vom Mittelwert entfernt sind (oberhalb und unterhalb des Mittelwertes liegen); mehr dazu unter https://de.khanacademy.org/math/statistics-probability/summarizing-quantitative-data
ein Histogramm gibt an wie häufig bestimmte Werte vorkommen
wir benutzen ein Kommando aus dem Paket (library) “rcompanion”
library(rcompanion)
plotNormalHistogram(d$tot.dur, col=c('powderblue')) # erstelle ein Histogramm, und zwar für die Werte der Variable tot.dur```
Kapitelübersicht
In diesem Kapitel lernen Sie, wie Sie mithilfe des Pakets “plyr” und der Funktion SummarySE unterschiedliche Mittelwerte und Varianzen berechnen können.
Paket
library(plyr)
Daten
Funktion
########### Function SummarySE #######
summarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE,conf.interval=.95, .drop=TRUE) {
require(plyr)
# neue Version, die mit fehlenden Daten umgehen kann: wenn na.rm==T, dann wird dieser Datenpunkt nicht gezählt
length2 <- function (x, na.rm=FALSE) {
if (na.rm) sum(!is.na(x))
else length(x)
}
# dieser Code erstellt die summary (die "Zusammenfassung" der Deskriptivstatistik)
datac <- ddply(data, groupvars, .drop=.drop,
.fun= function(xx, col, na.rm) {
c( N = length2(xx[,col], na.rm=na.rm),
mean = round(mean (xx[,col], na.rm=na.rm), digits=3),
sd = round(sd (xx[,col], na.rm=na.rm),digits=3)
)
},
measurevar,
na.rm
)
# Benenne die "mean" Spalte neu
datac <- rename(datac, c("mean"=measurevar))
datac$se <- round(datac$sd / sqrt(datac$N),digits=3) # Berechne den Standardfehler des Mittelwerts
# Berechne t-Statistik für das Konfidenzintervall:
# z.B., wenn das Konfidenzintervall .95 ist, dann nutze .975 (darüber/darunter), und nutze df=N-1
ciMult <- qt(conf.interval/2 + .5, datac$N-1)
datac$ci <- round(datac$se * ciMult,digits=3)
return(datac)
}
für die deskriptive Statistik sind Durchschnittswerte und eine Schätzung der Varianz besonders wichtig; mehr dazu unter https://de.statista.com/statistik/lexikon/definition/138/varianz/
Durchschnittswerte und Varianz können für verschiedene Datentypen berechnet werden (kontinuierliche Daten wie Reaktionszeiten oder binomiale Daten wie ja/nein-Entscheidungen)
Es gibt zwei Arten Durchschnittswerte und Varianz zu berechnen:
Sie sehen, dass sich die Mittelwerte im Prinzip zwischen den verschiedenen Arten der Aggregation nicht unterscheiden, aber die Varianz
Warum unterscheidet sich die Varianz?
Was bedeuten die Varianzunterschiede? Durch die verschiedenen Aggregierungen kann man ermitteln, wieviel “Streuung” (Noise) durch die zufällig ausgewählten Versuchspersonen zustande kommt und wieviel durch die zufällig ausgewählten Items
Warum zufällig? Sie hätte andere VPn testen können; Ihre Auswahl war zufällig; Sie hätten andere Items konstruieren können; Ihre Auswahl war zufällig
der Zufallsfaktor ist bei der Berechnung von Mittelwerten und besonders beim Berechnen statistischer Bedeutsamkeit ein wichtiges Konzept; es könnte ja sein, dass Ihre Ergebnisse in besonderem Maße von nur wenigen Versuchspersonen beeinflusst sind; hätten Sie andere Versuchspersonen ausgesucht, dann wäre vielleicht nicht das selbe Ergebnis zustande gekommen
im Idealfall sind Ihre statistischen Ergebnisse am Ende also nicht von der Zufälligkeit der Auswahl beeinflusst
wenn Sie einen Signifikanztest (z.B. t-Test oder ANOVA) machen, sollte dieser für beide Aggregierungsvarianten signifikant sein
moderne Methoden können den Einfluss der zufälligen Auswahl von Probanden und Item in einem Schritt berücksichtigen (“gemischte Modelle”)
zum Glück ist es sehr einfach Mittelwerte und Varianz in R zu berechnen, nämlich mit der library (plyr)
die wichtigste Funktion, die wir benötigen heißt “ddply”
die Struktur der Funktion sieht so aus
# DON'T RUN
ddply(datenset, .(Variable1, Variable2,...), summarize, was-zu-tun ist, wo-es-zu-tun-istz)
“was-zu-tun-ist” betrifft eine mathematische Operation, zum Beispiel “Mittelwert” (mean), “Standardabweichung” (sd), usw.
“wo es zu tun ist” betrifft die Spalte, auf die die Operation angewendet werden soll
Zum Beispiel:
# DON'T RUN
ddply(datenset,(Bedingung, Versuchsperson), summarize, mean(Messwert))
d <- read.csv("./raw data/test_data.csv", sep=";") # wir laden das Datenset test_data.csv und nennen es einfach "d"
str(d) # Datenstruktur ansehen
## 'data.frame': 24 obs. of 4 variables:
## $ Messwert : int 99 5 12 21 38 3 67 23 40 37 ...
## $ VP : int 1 2 3 1 2 3 1 2 3 1 ...
## $ Item : int 1 1 1 2 2 2 3 3 3 4 ...
## $ Bedingung: chr "A" "A" "A" "A" ...
library(plyr)
ddply(d, .(Bedingung), summarize, mean(Messwert),sd(Messwert))
## Bedingung ..1 ..2
## 1 A 39.66667 29.63822
## 2 B 63.50000 28.16348
grand_means <- ddply(d, .(Bedingung), summarize, durchschnitt= mean(Messwert),SD=sd(Messwert))
grand_means
## Bedingung durchschnitt SD
## 1 A 39.66667 29.63822
## 2 B 63.50000 28.16348
sub_aggregated <- ddply(d, .(Bedingung, VP), summarize, durchschnitt= mean(Messwert),SD=sd(Messwert))
sub_aggregated
## Bedingung VP durchschnitt SD
## 1 A 1 56.00 34.42867
## 2 A 2 31.00 22.49444
## 3 A 3 32.00 31.54890
## 4 B 1 77.25 16.62077
## 5 B 2 49.50 22.54625
## 6 B 3 63.75 40.12792
item_aggregated <- ddply(d, .(Bedingung, Item), summarize, durchschnitt= mean(Messwert),SD=sd(Messwert))
item_aggregated
## Bedingung Item durchschnitt SD
## 1 A 1 38.66667 52.36729
## 2 A 2 20.66667 17.50238
## 3 A 3 43.33333 22.18859
## 4 A 4 56.00000 18.08314
## 5 B 1 78.66667 17.09776
## 6 B 2 58.66667 38.03069
## 7 B 3 78.00000 12.12436
## 8 B 4 38.66667 29.26317
sub_mean <- ddply(sub_aggregated, .(Bedingung), summarize, Mittel= mean(durchschnitt),SD=sd(durchschnitt))
sub_mean
## Bedingung Mittel SD
## 1 A 39.66667 14.15392
## 2 B 63.50000 13.87669
item_mean <- ddply(item_aggregated, .(Bedingung), summarize, Mittel= mean(durchschnitt),SD=sd(durchschnitt))
item_mean
## Bedingung Mittel SD
## 1 A 39.66667 14.63127
## 2 B 63.50000 18.97659
GrandMeans <- summarySE(d, measurevar="Messwert", groupvars=c("Bedingung"))
GrandMeans
## Bedingung N Messwert sd se ci
## 1 A 12 39.667 29.638 8.556 18.832
## 2 B 12 63.500 28.163 8.130 17.894
by_subj <- summarySE(sub_aggregated, measurevar="durchschnitt", groupvars=c("Bedingung"))
by_subj
## Bedingung N durchschnitt sd se ci
## 1 A 3 39.667 14.154 8.172 35.161
## 2 B 3 63.500 13.877 8.012 34.473
man kann mit der summarySE-Funktion natürlich auch Mittelwerte für mehrer Bedingungen berechnen, ganz ähnlich wie wir das oben bei den Mittelwerten pro Bedingung pro Versuchsperson gemacht haben
das sieht dann im Prinzip so aus:
summarySE(sub_aggregated, measurevar="messvariable", groupvars=c("Bedingung1","Bedingung2", ...))
Kapitelübersicht
Die Visualisierung von erhobenen Daten ist ein wichtiger Schritt während der Datenanalyse, und zwar an zwei Stellen während des Auswertungsprozesses: 1. Beim Überprüfen der Rohdaten, z.B. um Unregelmäßigkeiten zu entdecken (wie Ausreißerwerte oder fehlende Daten); 2. Zur visuellen Darstellung von Ergebnissen. Damit werden wir uns in diesem Kapitel beschäftigen.
library(ggplot2) #Aktivieren des Packages aus der R "Bibliothek"
“ggplot2” kann neben der Datenvisualisierung auch bestimmte Berechnungen vornehmen
oft sind diese Berechnungen jedoch schon vor der eigentlichen Visualisierung nötig; damit beschäftigen wir uns in Teil 2
Grafiken (“Plots”) werden in RStudio in dem Fenster rechts unten angezeigt; man muss den Reiter “Plots” auswählen
Test_daten <- read.csv("./raw data/test_data.csv", sep=";") # wir laden das Datenset "test_data.csv" und nennen es einfach "d"
str(Test_daten) # Datenstruktur ansehen
## 'data.frame': 24 obs. of 4 variables:
## $ Messwert : int 99 5 12 21 38 3 67 23 40 37 ...
## $ VP : int 1 2 3 1 2 3 1 2 3 1 ...
## $ Item : int 1 1 1 2 2 2 3 3 3 4 ...
## $ Bedingung: chr "A" "A" "A" "A" ...
ggplot(data = Test_daten, aes(y = Messwert, x = Bedingung)) + # nimm Daten aus dem df "data", plotte die Messwerte, aufgeteilt nach Bedingung
geom_point() # produziere einfache Punkte
ggplot(data = Test_daten, aes(y=Messwert, x = VP, color = VP )) + # nimm Daten aus dem df "data", plotte die Messwerte, aufgeteilt nach der Variable "VP"; benutze verschiedene Farben für jeden Wert der Variable "VP"
ggtitle ("Mein erster Plot mit Überschrift") + # Titel der Grafik hinzufügen
geom_point() # produziere einfache Punkte
ggplot(data = Test_daten, aes(y=Messwert, x = factor(Item), color = factor(Item) )) + # nimm Daten aus dem df "data", plotte die Messwerte, aufgeteilt nach der Variable "Item"; benutze verschiedene Farben für jeden Wert der Variable "Item", beachte, dass die Ausprägungen der Variable diskret und nicht kontinuierlich sind
ggtitle ("Mein zweiter Plot mit Überschrift") + # Titel der Grafik hinzufügen
geom_point() # produziere einfache Punkte
ggplot(data = Test_daten, aes(y=Messwert, x = Bedingung )) + # nimm Daten aus dem df "data", plotte die Messwerte, aufgeteilt nach der Variable "Bedingung"
ggtitle ("Summary Plot") + # Titel der Grafik hinzufügen
stat_summary(fun.data=mean_se, geom="pointrange")
ggplot(data = Test_daten, aes(y=Messwert, x = Bedingung )) + # nimm Daten aus dem df "data", plotte die Messwerte, aufgeteilt nach der Variable "Bedingung"
ggtitle ("Summary Plot 2") + # Titel der Grafik hinzufügen
geom_point(color = "grey", size = 2)+
stat_summary(fun.data=mean_se, geom="pointrange", color = "red")+
theme_bw()
ggplot(data = Test_daten, aes(y=Messwert, x = Bedingung, fill = Bedingung )) +
ggtitle ("Summary Plot 3") + # Titel der Grafik hinzufügen
stat_summary(fun = mean, geom = "bar", width = 0.4) + # Breite der Säule angeben
stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.3)+ # Breite der "Fühler" angeben
geom_point(color = "red", size = 1)+
theme_bw()
ggsave(filename="./plots/plot1.jpg",width=5, height=5,dpi=300) # speichere den plot im Verzeichnis "plots" unter dem Namen plot 1 als jpg-Datei mit der Größe 5 (Höhe, Breite) und der Auflösung 300 dpi
Jetzt aggregieren wir die Daten zunächst über VPn und Items, berechnen dann Mittelwerte (der Mittelwerte) und Werte, die die Varianz angeben und plotten dann alles mit ggplot.
library(plyr)
library(ggplot2)
Test_daten <- read.csv("./raw data/test_data.csv", sep=";") # wir laden das df test_data.csv und nennen es Test_daten
sub_aggregated <- ddply(Test_daten, .(Bedingung, VP), summarize, durchschnitt= mean(Messwert))
sub_aggregated
## Bedingung VP durchschnitt
## 1 A 1 56.00
## 2 A 2 31.00
## 3 A 3 32.00
## 4 B 1 77.25
## 5 B 2 49.50
## 6 B 3 63.75
item_aggregated <- ddply(Test_daten, .(Bedingung, Item), summarize, durchschnitt= mean(Messwert))
item_aggregated
## Bedingung Item durchschnitt
## 1 A 1 38.66667
## 2 A 2 20.66667
## 3 A 3 43.33333
## 4 A 4 56.00000
## 5 B 1 78.66667
## 6 B 2 58.66667
## 7 B 3 78.00000
## 8 B 4 38.66667
sub_summary <- summarySE(sub_aggregated , measurevar="durchschnitt", groupvars=c("Bedingung"))
itm_summary <- summarySE(item_aggregated , measurevar="durchschnitt", groupvars=c("Bedingung"))
sub_summary
## Bedingung N durchschnitt sd se ci
## 1 A 3 39.667 14.154 8.172 35.161
## 2 B 3 63.500 13.877 8.012 34.473
itm_summary
## Bedingung N durchschnitt sd se ci
## 1 A 4 39.667 14.631 7.316 23.283
## 2 B 4 63.500 18.977 9.488 30.195
ggplot(data = sub_summary, aes(y= durchschnitt, x = Bedingung, color = Bedingung ))+ # selbsterklärend
ggtitle ("Titel der Grafik") + # Titel der Grafik hinzufügen
geom_point() + # produziere einfache Punkte
geom_errorbar(aes(ymin=durchschnitt-se, ymax=durchschnitt+se), width=.1) + # wir nutzen "se" für die Darstellung der Varianz
theme_bw()
ggplot(data = sub_summary, aes(y= durchschnitt, x = Bedingung, fill = Bedingung ))+ # selbsterklärend
ggtitle ("Titel der Grafik") + # Titel der Grafik hinzufügen
geom_bar(stat = "identity") + # produziere eine Säule
geom_errorbar(aes(ymin=durchschnitt-se, ymax=durchschnitt+se), width=.1) + # wir nutzen "se" für die Darstellung der Varianz
theme_bw()
was ist jetzt der Vorteil daran, dass wir die Mittelwerte und die Varianz außerhalb von ggplot berechnen?
ein wesentlicher Vorteil liegt daran, dass wir die Skalierung des Plots ändern können; das geht bei der Benutzung der “stat_summary”-Funktion (siehe Kapitel 6: “Plots, die Zusammenfassungen darstellen” ) innerhalb von ggplot nicht
schauen wir uns ein Beispiel an: Vergleichen Sie die folgenden beiden Plots und schauen Sie was sich im Code verändert hat
ggplot(data = sub_summary, aes(y= durchschnitt, x = Bedingung, color = Bedingung ))+ # selbsterklärend
geom_point() + # produziere einfache Punkte
geom_errorbar(aes(ymin=durchschnitt-se, ymax=durchschnitt+se), width=.1) + # wir nutzen "se" für die Darstellung der Varianz
scale_y_continuous(limits = c(0,130))+
theme_bw()
ggplot(data = sub_summary, aes(y= durchschnitt, x = Bedingung, color = Bedingung ))+ # selbsterklärend
geom_point() + # produziere einfache Punkte
geom_errorbar(aes(ymin=durchschnitt-se, ymax=durchschnitt+se), width=.1) + # wir nutzen "se" für die Darstellung der Varianz
scale_y_continuous(limits = c(30,80))+
theme_bw()
library(RColorBrewer)
ggplot(data = sub_summary, aes(y= durchschnitt, x = Bedingung, fill = Bedingung ))+ # selbsterklärend
scale_y_continuous("Average")+ # Wir passen den Namen auf der y-Achse an
scale_x_discrete("Condition")+ # Wir passen den Namen auf der x-Achse an
geom_bar(stat = "identity", width = 0.8) +
geom_errorbar(aes(ymin=durchschnitt-se, ymax=durchschnitt+se), width=.1, color = "black") + # wir nutzen "se" für die Darstellung der Varianz
scale_fill_brewer(palette="Spectral", "Condition")+ # welche Farbpalette soll genutzt werden? Außerdem Ändern der Bezeichnung der Legende in "Condition"
ggtitle("Barplot with customized colors\nusing RcolorBrewer")+ # \n stellt einen Zeilenumbruch dar
theme_dark()+ # wir benutzen das "dunkle" Template
theme(plot.title = element_text(size = 10, lineheight=.8, face="bold", hjust = 0.5),
axis.title.x = element_blank() ) # mit theme kann man das Aussehen des Plots in Bezug auf alle sichtbaren Elemente anpassen; in unserem Fall passen wir das Aussehen der Überschrift an (plot.title) und wir machen die Bezeichnung der X-Achse unsichtbar (axis.title.x)
Kapitelübersicht
In diesem Kapitel wird eine detaillierte Vorgehensweise bei der Datenanalyse als Beispiel vorgestellt, die sich aus allen bisherigen Kapiteln zusammensetzt und Sie bei einer echten Analyse von Daten verwenden können.
Glückwunsch! Sie haben Ihren ersten Datensatz erfolgreich bearbeitet!
Objekt erzeugen und es “objekt” nennen
objekt <- "mein Objekt"
Alle Objekte im Environment anzeigen
ls()
Objekt im Environment löschen
rm(objekt)
Alle Objekte im Environment löschen
rm(list = ls())
Alle Objekte im Environment löschen außer
rm(list=setdiff(ls(), c("a", "c"))) # löscht alle Objekte außer "a" und "b"
ein bereits installiertes Paket laden; in diesem Fall “plyr”
library(plyr)
checken, ob “readr” vorhanden ist, wenn nicht, dann installieren, wenn vorhanden, dann laden
if(!require(readr)){install.packages("readr")}
Vektoren erzeugen
# einen Vektor erzeugen
one <- c(1,2,3,4,5)
# noch einen Vektor erzeugen
two <- c(6,7,8,9,10)
Sequenzen erzeugen
# erzeuge einen Vektor "s" mit den Zahlen von 1 bis 140
s <- seq(1, 140, 1)
Werte wiederholen
# erzeuge einen Vektor mit dem Wort "Liste1", das 140 Mal wiederholt wird
t1 <- rep("Liste1",140)
Die Vektoren zu einem Datensatz zusammenfügen
A <- data.frame(one,two)
# Achtung! beide Vektoren müssen gleich lang sein!
Vektoren in Dataframes zusammenführen
# erzeuge ein Objekt mit Namen "add_info", das ein Dataframe ist, in dem die beiden Vektoren "s" und "t1" als Spalten enthalten sind
add_info <- as.data.frame(cbind(s,t1))
einen Teil (Anfang/Ende) eines Dataframes anzeigen
# head mit Angabe der "n" zeigt nur den Anfang eines df; n erlaubt jede beliebige Zahl
head(A, n = 3)
## one two
## 1 1 6
## 2 2 7
## 3 3 8
# tail mit Angabe der "n" zeigt nur das Ende eines df
tail(A, n = 5)
## one two
## 1 1 6
## 2 2 7
## 3 3 8
## 4 4 9
## 5 5 10
Eine Kopie von einem Dataframe erstellen
A.new <- A
einen Vektor an einen bestehenden Datensatz anbinden
df_new <- cbind(df, Vektor)
# Achtung! Dataframe und Vektor müssen gleich lang sein!
# Benenne die Spalten des df "add_info" um, und zwar in "index" und "Liste
colnames(add_info) <- c("index","Liste")
die Spaltennamen des df “A” ändern
colnames(A) <- c("good", "better")
Auf einzelne Werte im Dataframe zugreifen - per Spalten-/Zeilennummer
# erste Zeile, erste Spalte
A.new[1,1]
# fünfte Zeile, zweite Spalte
A.new[5,2]
Auf mehrere Werte zugreifen - Werte in Zeilen
# alle Werte in der zweiten Zeile
A.new[2, ]
Auf mehrere Werte zugreifen - Werte in Spalten
# alle Werte in der zweiten Spalte
A.new[, 2]
Auf mehrere Werte zugreifen - via Spalten-/Zeilennamen
# Option 1
df$spalten_name
#Option 2
df[,"spalten_name"]
#Option 3
df[ ,c("spalten_name1","spalten_name2",...)]
Spalten oder Zeilen löschen
# Spalte x löschen; x kann Zahl sein oder "Name"
A.new[,x] <- NULL
# Zeile x löschen
A.new[x, ] <- NULL
# jedes Subset beginnt mit
subset <- df[df$Variable1 ...,]
# je nachdem, was im Subset gewünscht ist, wird "..." ersetzt:
# das Subset besteht aus Zeilen, in denen der Wert 4 in der Spalte "col" vorkommt
subset <- df[df$Scol == 4,]
# das Subset besteht aus Zeilen, in denen der Wert 4 in der Spalte "col" nicht vorkommt
subset <- df[df$col != 4,]
# das Subset besteht aus Zeilen, in denen Werte größer 4 und kleiner 8 in der Spalte "col" vorkommen
subset <- df[df$col > 4 & df$col < 8,]
# das Subset besteht aus Zeilen, in denen Werte 4 oder 8 in der Spalte "col" vorkommen
subset <- df[df$Spalte == 4 | df$Spalte == 8,]
Wichtig: Die Operatoren | und & können auch in anderen Kontexten verwendet werden.
# erstelle ein Subset aus dem df data, bei dem in der Spalte "column" die Werte "Wert1", "Wert2", etc zu finden sind
subset <- data[(data$column %in% c("Wert1", "Wert2","Wert3","Wert4")), ]
# erstelle ein Subset aus dem df data, bei dem in der Spalte "column" NICHT die Werte "Wert1", "Wert2", etc zu finden sind - Ausrufezeichen beachten!
subset <- data[!(data$column %in% c("Wert1", "Wert2","Wert3","Wert4")), ]
# Das Datenset "pseudo_et_data.csv" laden und es "pseudo_et_data" nennen
pseudo_et_data <- read.csv("./raw data/pseudo_et_data.csv", sep=";")
library(plyr)
files = list.files("./raw data", pattern="*.csv") # Liste aller Dateien im Unterverzeichnis erstellen
path = paste("./raw data",files,sep="") # für alle Dateien den Pfad erstellen
myfiles <- lapply(path,function(files){
read.csv(files, header=T, skip=0,encoding="UTF-8", stringsAsFactors=F)
})
# Name der Datei als neue Spalte einfügen
for( i in seq_along(myfiles)){
myfiles[[i]]$subject_nr <- rep(files[i],nrow(myfiles[[i]]))
}
for (i in 1: length(myfiles)) {myfiles[[i]]<- ddply(myfiles[[i]], .(subject_nr), function(X) data.frame(X, Trial_Index=1:nrow(X)))}
#alle DF in der Liste "myfiles" werden zu einem dataframe gemergt
new <- myfiles[[1]]
for (i in 2:length(myfiles)) {
new <- merge(new, myfiles[[i]], all=TRUE)
}
## Nutzen Sie folgenden Code, nachdem Sie das "#" entfernen, um nur relevante Spalten auszuwählen ##
# raw <- new[c("SPALTEN_name_1","SPALTEN_name_2","...")] #SPALTEN_name: Alle relevanten Spalten aus den Rohdaten angeben
## Beispielcode
raw <- new[c("Block","ExpMode","File_1","Syllables","block_nr","condition","subject_nr","Trial_Index")]
str(raw)
# Objekt im Computer abspeichern
write.csv2(raw, file = "./pre_pro/proc_data.csv")
# Datei laden
data <- read.csv("./pre_pro/proc_data.csv")
d <- join(data,objekt, by = c("Bedingung_1","Bedingung_2"), type = "left", match = "first")
# Bedingung 1 und 2 stehen jeweils für die Stellen, für die es einen Match geben soll
Einfache Methode (ohne Extra-Funktionen)
# Suche nach ".csv", wenn gefunden, durch "" (nichts) ersetzen (=löschen)
df$subject_nr <- gsub(".csv","",df$subject_nr)
# Suche nach "subject-", wenn gefunden, durch "" (nichts) ersetzen (=löschen)
df$subject_nr <- gsub("subject-","",df$subject_nr)
Suchen und Ersetzen mit Funktion “gsr”
# vor dem Ausführen des folgenden Codes die GSR Funktion laden; siehe Ende des Dokuments
df$spalte <- gsr(df$spalte, c("Falsch1","Falsch2", "..."),
c("Richtig1","Richtig2","..."))
# Datenstruktur ansehen
str(d)
#Anzeigen, welche unterschiedlichen Werte, es in einer Variablen gibt
unique(df$Variable1)
# anzeigen, wie viele Datenzeilen gibt es für jeden einzigarten Wert in der Spalte "sub"
xtabs(~ sub, d)
# die Kreuztabellen als df speichern
objekt1 <- as.data.frame(xtabs(~ sub, d))
# eine kurze Übersicht über die wichtigsten Merkmale von numerischen Werten anzeigen
summary(d)
wichtig: die Variablen müssen numerische Werte zurückgeben
# einfache Varianzberechnung
var(df$Variable1)
# einfache Berechnung von Standardabweichung
sd(df$Variable1)
# die Grand Means unterschiedlicher Bedingungen berechnen und in die Datentabelle hinzufügen
grand_means <- ddply(df, .(Bedingung), summarize, mean(Messwert),sd(Messwert))
# wenn gewünscht ist, dass der Mittelwert und die Standardabweichung jeweils einen spezifischen Namen in der Datentabelle haben, dann kann man 'Name_Messwert =' einfügen, z.B.:
ddply(df, .(Bedingung), summarize, Name_Messwert = mean(Messwert),sd(Messwert))
# Mittelwerte der Bedingung berechnen, aufgeteilt nach einer weiteren Variablen (z.B. Versuchsperson)
VP_aggregated <- ddply(df, .(Bedingung, VP), summarize, durchschnitt= mean(Messwert),SD=sd(Messwert))
# natürlich lassen sich auch wieder die Mittelwerte der Mittelwerte berechnen
VP_mean <- ddply(VP_aggregated, .(Bedingung), summarize, Mittel= mean(durchschnitt),SD=sd(durchschnitt))
Interessant zu wissen: Mit summarize können nicht nur Mittelwerte & Standardabweichungen berechnet werden!
# Varianz nach Bedingung berechnen
ddply(df, .(Bedingung), summarize, Varianz = var(Messwert), SD = sd(Messwert))
# Es ist auch möglich die Kennwerte durch eine einzige große Funktion zu berechnen
# nachdem diese geladen wurde (s. Kapitel 6) kann folgender Code verwendet werden
df_summary <- summarySE(df , measurevar="durchschnitt", groupvars=c("Bedingung"))
# Col steht für die Farbe des Plots
boxplot(df$Variable1, col=c('powderblue'))
# der Boxplot wird nach den unterschiedlichen Ausprägungen von Variable2 aufgeteilt und zeigt die Werte der Variable 1 an
boxplot(Variable1 ~ Variable2, data = df, col=c('powderblue'))
# Histogramm erstellen (z.B. um mit dem Auge auf Normalverteilung überprüfen)
plotNormalHistogram(df$Variable1, col=c('powderblue'))
# Daten aus dem df "data" nennen und die Messwerte, aufgeteilt nach Bedingung plotten
# Titel der Grafik hinzufügen
# einfache Punkte produzieren
ggplot(data = Test_daten, aes(y = Messwert, x = Bedingung)) + ggtitle ("Mein Plot mit Überschrift") + geom_point()
library(RColorBrewer)
# kann verwendet werden, um die Farben in den Plots anzupassen
# Plot speichern
ggsave(filename="../gfx/plot1.jpg",width=5, height=5,dpi=300)
plyr:
readr:
rcompanion:
ggplot2:
RColorBrewer:
Verwendete Pakete müssen immer zitiert werden, wenn Sie Ihr Skript in Ihre Arbeit einfügen wollen.
Wie findet man die richtige Zitation heraus?
citation("dplyr") # zeigt die richtige Zitation des Pakets "dplyr" an
##
## To cite package 'dplyr' in publications use:
##
## Hadley Wickham, Romain François, Lionel Henry and Kirill Müller
## (2020). dplyr: A Grammar of Data Manipulation. R package version
## 1.0.2. https://CRAN.R-project.org/package=dplyr
##
## A BibTeX entry for LaTeX users is
##
## @Manual{,
## title = {dplyr: A Grammar of Data Manipulation},
## author = {Hadley Wickham and Romain François and Lionel {
## Henry} and Kirill Müller},
## year = {2020},
## note = {R package version 1.0.2},
## url = {https://CRAN.R-project.org/package=dplyr},
## }
SummarySE function zur Berechnung von Mittelwerten
########### Function SummarySE #######
summarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE,conf.interval=.95, .drop=TRUE) {
require(plyr)
# neue Version, die mit fehlenden Daten umgehen kann: wenn na.rm==T, dann wird dieser Datenpunkt nicht gezählt
length2 <- function (x, na.rm=FALSE) {
if (na.rm) sum(!is.na(x))
else length(x)
}
# dieser Code erstellt die summary (die "Zusammenfassung" der Deskriptivstatistik)
datac <- ddply(data, groupvars, .drop=.drop,
.fun= function(xx, col, na.rm) {
c( N = length2(xx[,col], na.rm=na.rm),
mean = round(mean (xx[,col], na.rm=na.rm), digits=3),
sd = round(sd (xx[,col], na.rm=na.rm),digits=3)
)
},
measurevar,
na.rm
)
# Benenne die "mean" Spalte neu
datac <- rename(datac, c("mean"=measurevar))
datac$se <- round(datac$sd / sqrt(datac$N),digits=3) # Berechne den Standardfehler des Mittelwerts
# Berechne t-Statistik für das Konfidenzintervall:
# z.B., wenn das Konfidenzintervall .95 ist, dann nutze .975 (darüber/darunter), und nutze df=N-1
ciMult <- qt(conf.interval/2 + .5, datac$N-1)
datac$ci <- round(datac$se * ciMult,digits=3)
return(datac)
}
gsr function zum Suchen & Ersetzen
gsr <- function(Source, Search, Replace)
{
if (length(Search) != length(Replace))
stop("Search and Replace Must Have Equal Number of Items\n")
Changed <- as.character(Source)
for (i in 1:length(Search))
{
cat("Replacing: ", Search[i], " With: ", Replace[i], "\n")
Changed <- replace(Changed, Changed == Search[i], Replace[i])
}
cat("\n")
Changed
}
Gerwien, J. (2020). pseudo_et_data.tab. Retrieved from: https://doi.org/10.11588/data/UCRWJ4/FSZIGN
Gerwien, J. (2020). test_data.tab. Retrieved from: https://doi.org/10.11588/data/UCRWJ4/NHBJIO
Teil 1
Die Lösung ist die Aufgabe
Teil 2
Die Lösung ist individuell verschieden
Teil 3
colnames(df) <- c("Spalte1", "Spalte2","Spalte3", "Spalte4","Spalte5", "Spalte6","Spalte7")
Teil 4
df$AOI <- gsub("triangle","Dreieck",df$AOI)
d <- read.csv("./raw data/pseudo_et_data.csv", sep=";")
object1 <- xtabs(~ AOI + sub, d)
str(object1)
## 'xtabs' int [1:4, 1:7] 7 0 7 6 7 6 7 0 6 6 ...
## - attr(*, "dimnames")=List of 2
## ..$ AOI: chr [1:4] "circle" "rectangle" "square" "triangle"
## ..$ sub: chr [1:7] "Alice" "Ben" "bruno" "Eduard" ...
## - attr(*, "call")= language xtabs(formula = ~AOI + sub, data = d)
objekt2 <- as.data.frame(xtabs(~ sub + condition, d))
str(objekt2)
## 'data.frame': 28 obs. of 3 variables:
## $ sub : Factor w/ 7 levels "Alice","Ben",..: 1 2 3 4 5 6 7 1 2 3 ...
## $ condition: Factor w/ 4 levels "A","B","C","D": 1 1 1 1 1 1 1 2 2 2 ...
## $ Freq : int 5 5 5 5 5 6 5 5 5 5 ...
boxplot(hits ~ sub, data = d)
library(plyr)
d <- read.csv("./raw data/test_data.csv", sep=";")
variance <- ddply(d, .(Bedingung), summarize, Varianz=var(Messwert))
variance
## Bedingung Varianz
## 1 A 878.4242
## 2 B 793.1818
head(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa