Ein Tutorial zum Selbststudium von Johannes Gerwien, unter Mitarbeit von Franziska Arnold und Tamaki Ogura

  • Version 1.0.1, März 2021
  • gefundene Fehler und Feedback bitte an
  • 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.

    1 Grundlagen

    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.

    1.1 Was heißt Programmieren (in R)?

    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.

    1.2 Was ist R Studio?

    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.

    1.3 Installation

    Sie müssen zwei Dinge installieren (am besten in der unten angegebenen Reihenfolge):

    1. R-Hauptprogramm: https://ftp.fau.de/cran/ (Windows, Mac, Linux)
    2. R-Studio: https://rstudio.com/products/rstudio/ (R Studio Desktop, Open-Source Edition)

    1.4 R Studio Benutzeroberfläche

    1.5 Erläuterungen zur Benutzeroberfläche

    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.

    1.5.1 Editorfenster (1)

    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:

    1. die Analyse zu dokumentieren, also alle Einzelschritte abzuspeichern
    2. die Analyse für sich und andere nachvollziehbar zu machen und eventuell Fehler zu entdecken
    3. dieselbe Analyse (oder Teile davon) auf verschiedene Datensets anwenden

    1.5.2 Konsole (2)

    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.

    1.5.3 Environment, History, etc. (3)

    • Environment: hier wird z.B. gezeigt, welche Variablen und Daten in R Studio erstellt worden sind, also alles, was man in R Studio erzeugt oder importiert hat
    • Sie können die meisten Objekte anklicken, um sich ihren Inhalt anzeigen zu lassen
    • Außerdem findet man in diesem Fenster wichtige Schaltflächen, zum Beispiel “Import Dataset”

    • History: alle Befehle, die in der Konsole ausgeführt wurden, werden hier als Liste gezeigt

    1.5.4 File, Plots, Packages etc. (4)

    • File: hier werden Ordner und Daten gezeigt, die auf dem Laptop gespeichert sind. Man kann hier eine einzelne Datei einfach durch das Klicken in R Studio öffnen
    • Plots: wenn man eine Grafik erstellt, wird sie hier gezeigt. Die erstellte Grafik kann außerdem als ein Bild oder eine PDF-Datei exportiert werden

    • Packages: Hier ist die Verwaltung von Paketen möglich. Was ein Paket bei R ist, wird später erklärt

    1.6 Grundlegendes Konzept

    1.6.1 Auf Daten zugreifen

    • 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:

      • Datenpunkte (in den meisten Fällen Zahlen) sind in Vektoren abgelegt und Vektoren sind in Dataframes zusammengefasst
      • Datenpunkte werden benutzt, um andere Datenpunkte zu identifizieren

    • in der Grafik stellt der graue Kasten einen Dataframe dar
    • die vertikalen Linien sind Vektoren
    • die grauen Punkte sind Werte
    • Stellen Sie sich vor, im roten Vektor stehen die Namen von Versuchspersonen; sagen wir es gibt drei Versuchspersonen, für die jeweils mehrere Werte verfügbar sind (grüner Vektor); jetzt können Sie über den Namen einer bestimmten Versuchsperson alle Werte im grünen Vektor identifizieren

    1.7 Erste Schritte

    1.7.1 Code in R Studio eingeben

    • Sie können Code direkt in die Konsole eintippen
    • in den meisten Fällen ist es aber besser, den Code zunächst in einem Skript “vorzubereiten”; so können Sie den Code als .R Dokument speichern und dadurch später auch besser nachvollziehen, was Sie eigentlich wie gemacht haben

    • um ein Code-Chunk (ein Kommando im Skript) auszuführen, bewegen sie den Cursor in die entsprechende Zeile und drücken dann cmd+enter (Mac) oder strg/ctrl+enter (Windows); Sie müssen die Zeile nicht vollständig markieren!

    • einen Code ausführen nennen wir RUN

    • Sie können auch mehrere oder alle Kommandos auf einmal starten lassen; dafür markieren Sie alle Kommandos und drücken wieder cmd+enter bzw. strg/ctrl+enter
    • Tipp: manchmal merkt man beim Ausführen vieler Kommandos auf einmal, dass man einen Fehler im Skript hat; wenn man den Fehler im Skript gefunden und korrigiert hat, kann man, ohne alles nochmal zu markieren mit Re-RUN alle Kommandos nochmal ausführen, inklusive des korrigierten Codes; dafür drückt man cmd+shift+P (Mac) oder Ctrl+Shift+P (Windows)
    • Viele weitere nützliche Shortcuts: https://support.rstudio.com/hc/en-us/articles/200711853-Keyboard-Shortcuts

    1.7.2 Mein erster Code

    • in R erstellt man “Objekte”; dabei gibt man immer den Namen des Objektes an und einen Pfeil <-, der in etwa gleichbedeutend mit “=” ist
    • das, was im Folgenden in einer Box grau unterlegt ist, können Sie kopieren und in Ihr Skript/Ihre Konsole einfügen; das, was in einer Box weiß unterlegt erscheint, ist das Resultat Ihres Kommandos
    objekt <- "mein erstes Objekt" # Objekt erstellen
    objekt                         # Objekt ansehen
    ## [1] "mein erstes Objekt"
    • Objekte können verschiedenen Typs sein: Vektoren, Dataframes, Tables, Grafiken, … (Dazu später mehr: Kapitel 2 )
    • Objekte werden in R gespeichert und befinden sich im “Environment”; Sie können bei Bedarf angesehen und auf vielfältige Art und Weise bearbeitet werden
    • auch wenn Sie zum Beispiel eine Excel-Tabelle haben, die Sie in R bearbeiten wollen (zur Datenauswertung), wird diese Tabelle zunächst als Objekt in R importiert (dazu später mehr: Kapitel 4 )
    • Objekte können aus R herausexportiert werden, sodass Sie mit anderen Programmen geöffnet werden können

    1.8 “Stay organized”

    1.8.1 Ein R Studio-Projekt anlegen

    • Erstellen Sie für dieses Tutorial einen neuen Ordner mit dem Namen “Tutorial” auf Ihrem Computer
    • Klicken Sie in R Studio auf Datei (File) > Neues Projekt (New Project)

    • Im sich öffnenden Fenster wählen Sie die zweite Option (“Existing Directory”)

    • Suchen Sie den Ordner “Tutorial” und Klicken Sie “Erstellen” (“Create”)

    1.8.2 Chaos auf dem Computer vermeiden

    • man kann beim Arbeiten mit R sehr schnell den Überblick verlieren; deshalb sollte man sich bestimmte Angewohnheiten zulegen

    Ordnerstruktur von Projekten

    • R-Projekte sollten am besten immer demselben Aufbau folgen
    • meine R-Projekte sind immer so aufgebaut wie in der Abbildung dargestellt
    • es gibt einen Ordner für Skript-Dateien (scripts), einen Ordner für Grafiken (plots), einen Ordner für Rohdaten (raw data), einen Ordner für vorverarbeitete Daten (processed data) und einen Ordner für Resultate (results)
    • Ihr Ordner sollte jetzt so aussehen, wie in der folgenden Abbildung

    1.8.3 Chaos im R Studio Environment vermeiden

    • aber auch im R Environment kann schnell Chaos entstehen
    • deshalb ist es wichtig zu wissen, wie man Objekte löscht

    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)

    1.9 Installation von Paketen (“packages”/“libraries”)

    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.

    1.9.1 Pakete (“libraries”) aktivieren

    • Um ein Paket verwenden zu können, muss es zunächst aktiviert werden.
    • Das können Sie manuell tun: Klicken Sie auf “Packages” im Bereich 4 (siehe oben)
    • Da können Sie alle Pakete verwalten, die in R Studio vorhanden sind
    • Wenn Pakete verfügbar sind, werden sie in der Übersicht auftauchen
    • Sie können die Pakete entweder durch Klicken der Checkbox in der Packages-Übersicht aktivieren oder durch das Eingeben eines Befehls.
    • das Laden eines Paketes ist immer notwendig, wenn Sie R Studio einmal beendet haben und dann erneut starten
    library(base) # ein bereits installiertes Paket laden
    • das Laden eines Paketes sollte immer am Anfang eines Skripts passieren
    • sinnvoll, wenn Sie Code erstellen und diesen Code an andere weitergeben wollen

    1.9.2 Pakete manuell downloaden und installieren

    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"

    • Klicken Sie nun auf “Install” unter “Packages”. Dann wird ein kleines Pop-up-Fenster gezeigt.

    • Geben Sie den Namen von Paketen ein, die Sie herunterladen wollen und klicken Sie dann auf “Install”.

    1.9.3 Pakete automatisch downloaden und installieren

    • Sie können Pakete auch automatisch laden bzw. herunterladen, für den Fall, dass es noch nicht installiert ist
    if(!require(readr)){install.packages("readr")} # checken, ob "readr" vorhanden ist, wenn nicht, dann installieren, wenn vorhanden, dann laden
    ## Loading required package: readr

    1.10 Programmier-Slang

    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:

      • unter einem Kommando versteht man einen speziellen Befehl, der uns bei der Bearbeitung sowie Auswertung von Daten hilft
      • z.B. mit dem Kommando “colnames” können alle Spaltennamen, die eine Datei enthält, angezeigt werden, ohne dass man selbst in die Datei reingucken muss
      • bei R gibt es noch viele weitere nützliche Kommandos, die Bearbeitungs- sowie Auswertungsprozesse vereinfachen, aber diese lernen wir erst später kennen
    • Script:

      • ein Script ist eine Abfolge von mehreren Befehlen, die in einer bestimmten Reihenfolge (von oben nach unten) ausgeführt wird
    • Paket:

      • nützliche, mächtige Werkzeuge, die ermöglichen, z.B. Ergebnisse der Datenauswertung als schöne Grafiken darzustellen
      • ein Paket kann einfach in R Studio installiert werden
    • Objekt:

      • R arbeitet nicht mit Dateien sondern mit sogenannten “Objekten”
      • Objekte beinhalten Daten
      • Wenn Sie eine Datei, die Ihre auszuwertenden Daten beinhaltet, in R bearbeiten wollen, dann weist R die Daten in Ihrer Datei zunächst einem Objekt zu; alle weiteren Analyseschritte geschehen dann mit diesem Objekt, nicht mit der Datendatei
    • Zuweisung:

      • Objekte entstehen durch Zuweisungen
      • das geschieht in der Regel mit “<-”
      • Im Beispiel erstellen wir ein Objekt, das aus dem Ergebnis von 1+1+1+1 bestehen soll
    objekt <- 1+1+1+1
    • Vektor:

      • ein Vektor beinhaltet eine Verkettung von Werten
      • Vektoren können beliebig lang sein; bei der Arbeit mit R benötigt man häufig Vektoren, die mehrere Hundert, mehrere Tausend oder sogar mehrere Millionen Werte erfassen
      • im Beispiel erstellen wir einen Vektor, der aus den Zahlen 1, 3, 5, 7 besteht
      • die Reihenfolge der Werte bleibt immer gleich
    vector <- c(1, 3, 5, 7)
    • Dataframe:
      • R Studio importiert zu analysierende Daten als Dataframe (wir kürzen häufig mit “df” ab)
      • ein Dataframe sieht wie eine Tabelle aus und besteht aus mehreren Vektoren, welche jeweils einer Spalte der Tabelle entsprechen
      • man kann z.B. eine csv- oder Excel-File als Dataframe importieren

    • Pfad:
      • unter einem Pfad versteht man einen “Weg” zu einem Ort auf dem Computer, an dem sich eine Datei befindet
      • Eine Datei kann eine csv-Datei sein, oder auch z.B. eine Graphik (jpg oder png-Datei), einen Text (text-Datei), oder auch ein anderes R-Skript (R-Datei)
      • Ein Pfad besteht aus einer durch Schrägstriche getrennten Liste von Ordnernamen, die zu einer zu importierenden Datei führt. Dies können Sie sich wie eine Baumstruktur vorstellen:
      • für gewöhnlich befindet sich die Datei, die Sie für die Datenanalyse importieren möchten, in einem Unterordner Ihres R-Studio-Projekts (in unserem Fall befinden sich zwei Testdatensätze im Unterordner “raw data”)
      • Pfade werden in R immer in englische Anführungsstriche ("") gesetzt
      • Ein (vollständiger) Pfad kann zum Beispiel folgendermaßen aussehen:
    (Mac) "~/Users/username/Desktop/Tutorial/raw data/" 
    (Windows) "C:/Users/username/Desktop/Tutorial/raw data"
    • relative Pfade

      • Sie müssen nicht immer den vollständigen Pfad angeben
      • es empfiehlt sich sogar eher sogenannte “relative Pfade” zu benutzen
      • Dabei geht R Studio davon aus, dass Sie Daten laden möchten, die sich in ihrem aktuellen Projektverzeichnis befinden; z.B., wie bei uns, im Ordner “raw data”
    (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:

      • es ist sehr wichtig, dass man Code übersichtlich und verständlich schreibt, damit er für andere Personen auch gut nachvollziehbar ist
      • dazu dienen Kommentare! Einen Kommentar kann man als Notiz für Menschen verstehen, um den Code in “menschliche Sprache” zu übersetzen
      • bei R ist ein Kommentar durch # gekennzeichnet
      • hier beschreibt der Kommentar, dass mit dem Code ein Wert einer Variable zugewiesen wird
      • ein Kommentar kann an jeder beliebigen Stelle geschrieben werden
    # 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

    2 Daten laden und verändern

    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.

    2.1 Vorbereitung

    Daten runterladen

    Wir verwenden in diesem Kapitel und im nächsten Kapitel ein paar Testdaten. Laden Sie bitte die folgenden Dateien:

    • pseudo_et_data.csv
    • test_data.csv

    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.

    2.2 Datentabellen in R öffnen

    2.2.1 Datei per Hand öffnen

    • es gibt viele Möglichkeiten, eine Datentabelle in R zu öffnen
    • man kann die “Import Dataset”-Schaltfläche im Environment-Fenster benutzen
    • oder man kann eine Tabelle mit einem Kommando öffnen

    • es öffnet sich ein Navigationsfenster

    • es öffnet sich ein Import-Fenster; wählen Sie die Datei und klicken Sie auf “öffnen”

    • im oberen Teil sehen Sie, was R versucht zu importieren; im unteren Teil sehen Sie, wie R versucht die Daten zu importieren
    • beachten Sie die Optionen auf der linken Seite und probieren Sie aus, was die unterschiedlichen Einstellungen verursachen

    2.2.2 Datei per Code öffnen

    • wenn Sie Daten per Kommando importieren wollen, müssen Sie wissen, wo sich Ihre Daten auf Ihrem Gerät bzw. Ihrer Festplatte befinden
    • wir verwenden die Ordnerstruktur, die wir in Kapitel 1 beschrieben haben; das zu importierende Datenset befindet sich im Unterordner “raw data”
    • die Datentabelle, die wir importieren möchten, heißt “pseudo_et_data.csv”
    • der Code zum Importieren sieht so aus:
    pseudo_et_data <- read.csv("./raw data/pseudo_et_data.csv", sep=";")
    • der Code bedeutet:
      • erzeuge ein Objekt “pseudo_et_data” (den Namen können Sie natürlich selbst wählen);
      • “<-” bedeutet das Objekt “pseudo_et_data” besteht aus …
      • “read.csv” ist der Befehl, der ausgeführt werden soll (Einlesen der CSV-Datei);
      • ./raw data/pseudo_et_data.csv gibt den Pfad und die Datei selbst an, wobei der “.” bedeutet “schaue von dort aus, wo du bist, in den Ordner raw data”; “der Ordner”raw data" befindet sich auf derselben Ebene, wie die Projektdatei (in unserem Beispiel heißt diese Projektdatei “Tutorial.Rproj”)
      • “sep=”;"" bedeutet, Datenspalten sind durch Semikolon getrennt

    2.2.3 Mehr zu Pfaden

    • Wie wir oben gesehen haben, müssen wir einen richtigen Pfad zum Ordner eingeben, immer wenn wir eine Datei aus einem anderen Ordner oder einem anderen Speicherplatz laden wollen.
    • Informieren Sie sich noch einmal in Kapitel 1 (“Grundlagen”) zum Thema Pfade

    2.2.4 Objekt auf dem Computer abspeichern

    • schauen wir uns auch noch an, wie man Daten aus R heraus exportiert
    • als Übung speichern wir unseren “dataframe pseudo_et_data” als .csv-Datei im Ordner “processed data” ab (“processed data” ist Teil der von uns in Kapitel 1 angelegten Ordnerstruktur)
    • Achten Sie wieder auf die richtige Angabe des Pfads
    write.csv2(pseudo_et_data, file = "./processed data/proc_data.csv")

    2.3 Datentypen

    • jede Tabelle, die “echte” Daten aus einem Experiment enthält besteht aus Vektoren, die unterschiedliche Datentypen beherbergen, zum Beispiel Zahlen (“numeric”), Buchstaben(ketten) (“character”) oder “Faktoren”(“factors”)
    • der Datentyp hat wichtige Auswirkungen darauf, was man mit den einzelnen Werten in einem Vektor machen kann
    • mit dem Kommando str() kann man sich den Datentyp anzeigen lassen; “str” steht für “Struktur”, neben dem Datentyp werden weitere Infos angegeben
    • um dies zu illustrieren, laden wir zunächst einen Dataframe, welches automatisch als Teil der R-Installation zur Verfügung steht
    data(iris) #Laden des R internen df "iris"
    • wir schauen uns die ersten 5 Datenzeilen an
    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
    • wir verwenden str(), um Informationen über die enthaltenen Datentypen zu erhalten
    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 ...
    • alle, außer eine Spalte enthält numerische Informationen (Zahlen); die letzte Spalte enthält Informationen, die als Faktor definiert sind, wobei Faktoren oft die unabhängigen Variablen sind
    • es gibt noch viele Details zu Datentypen, die für uns am Anfang aber keine Rolle spielen; “integer” zum Beispiel, ist eine Subkategorie von “numeric”
    • wichtig für uns ist: auf “character” und “factor”-Daten greift man mit Anführungszeichen zu ("“), aber auf numeric/integer Daten greift man ohne Anführungszeichen zu (”") zu; das werden Sie unten noch sehen; als Beispiel an dieser Stelle:
    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
    • wir machen dasselbe wie oben noch einmal mit dem df “pseudo_et_data”
    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" ...

    2.4 Erste Befehle zum Erstellen von “sinnvollen” Objekten

    2.4.1 Werte, Vektoren, Dataframes erstellen, löschen, umbenennen

    • erstellen wir zunächst einen Vektor, der fünf Zahlen beherbergt
    • “c” steht für “combine”; der Befehl unten bedeutet also: “Erstelle einen Vektor mit dem Namen ‘one’ und kombiniere dafür die Zahlen 1, 2, 3, 4, 5”
    one <- c(1,2,3,4,5) # it’s a vector
    • wir erstellen noch einen Vektor, der fünf Buchstaben beherbergt
    • Buchstaben(ketten) müssen in Anführungsstrichen angegeben werden
    two <- c("A","B","C","D","E") # it’s another vector
    • wir können beide Vektoren in einem Dataframe zusammenfassen
    A <- data.frame(one,two) # let’s combine them in a df
    • schauen wir uns den entstandenen df mal an; 3 Möglichkeiten:
    1. im Environment auf den Namen klicken (“A”)
    2. in der Konsole den Namen eingeben
    3. meistens bestehen dfs aus vielen hundert Zeilen; um nur die ersten n Zeilen zu sehen head() benutzen; für die letzten n Zeilen tail()
    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
    • wir ändern die Spaltennamen des df “A” mit colnames() und überprüfen das Resultat
    • außerdem löschen wir die beiden Vektoren “one” und “two”
    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)
    • wir erstellen noch einen Vektor und fügen ihn dem df “A” hinzu
    • wir kontrollieren das Resultat
    • wir erstellen eine Kopie von “A” mit dem Namen “A.new”
    • wir löschen den ersten df “A”
    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
    • oh nein, jetzt haben wir den dritten Vektor zweimal hinzugefügt; wie entfernen ihn aus dem df “A.new”?

    2.5 Auf Spalten, Zeilen und Werte zugreifen

    • das generelle Format ist Folgendes: dataframe[Zeile, Spalte]
    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
    • wir können Zeilen und Spalten aus einem df auch wieder als Vektor speichern
    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
    • wir wollten die 4. Spalte im df “A.new” löschen, weil wir Vektor “three” aus Versehen zum df hinzugefügt haben
    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

    2.5.1 andere Möglichkeit, auf Spalten zuzugreifen

    • statt mit eckigen Klammern zu arbeiten, kann man auch so vorgehen: dataframe$Spaltenname
    A.new$ok
    ## [1] 1 0 0 0 1

    2.5.2 andere Möglichkeit, auf Werte zuzugreifen

    • Wir können statt der Spaltennummer auch ihren Namen verwenden
    A.new[2,"ok"] # Alternative zu A.new[2,3]; der Name der dritten Spalte ist "ok"
    ## [1] 0

    2.6 Subsets erstellen

    • bei statistischen Analysen kommt es häufig vor, dass nicht das gesamte Datenset von Interesse ist; wenn Sie zum Beispiel Daten von “Filler” und “kritischen” Stimuli erhoben haben, dann interessieren Sie sich vielleicht zunächst nur für die “kritischen” Daten
    • um nur einen Teil der Daten ausführlich zu betrachten werden sog. Subsets erstellt
    • Subsets erstellt man in R, indem man Bedingungen angibt, durch die nur bestimmte Zeilen eines Dataframes ausgewählt werden, nämlich, die, die den angegebenen Bedingungen entsprechen
    • als Beispiel erstellen wir zunächst ein Subset für alle Autos mit 4 Zylindern im “mtcars”-Datenset
    • “mtcars” ist wie “iris” ein R-eigener Dataframe
    • schauen Sie sich gerne zunächst das gesamte Datenset an
    # 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
    • Mit “unique” wird eine Datei auf doppelte bzw. mehrfache Einträge überprüft und gibt den Datensatz ohne Duplikate zurück.
    • es gibt Autos mit 4, 6 und 8 Zylindern
    • jetzt erstellen wir das Subset für Autos mit 4 Zylindern
    • ein Subset ist genau wie alles andere in R ein “Objekt”, deshalb können wir die übliche Schreibweise verwenden: objekt <- …
    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
    • wir schauen uns das Subset an, zumindest die ersten fünf Zeilen
    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
    • die Bedingungen, mit denen man ein Subset erstellt, können auch “negativ” definiert sein; wir erstellen zur Illustration ein Subset aus dem Dataframe mtcars, in dem Autos mit 4 Zylindern ausgeschlossen sind; statt == verwenden wir !=, was so viel bedeutet wie “ist nicht”
    • wir betrachten das Subset mit view() (wieder auskommentiert, wie oben) und wir überprüfen mit unique() erneut, wie viele Typen es in der Kategorie Zylinder gibt
    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
    • Subsets können auch durch komplexe Bedingungen erstellt werden, indem mehrere Bedingungen miteinander kombiniert werden
    • zur Illustration, erstellen wir ein Subset, bei dem die Werte in der Spalte Zylinder größer sein sollen als 4 und kleiner als 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)
    • noch ein Beispiel für eine komplexe Bedingung; wir erstellen ein Subset, bei dem die Zahl in der Spalte “cyl” entweder 6 oder 8 entspricht
    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)
    • “|” bedeutet “oder” und “&” bedeutet “und”; diese beiden Operatoren können miteinander innerhalb einer komplexen Bedingung kombiniert werden

    2.6.1 Subsets erstellen - vereinfachte Schreibweise

    # 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")), ]

    2.7 Daten erzeugen

    • Sie haben oben bereits einige Wege kennengelernt, wie Sie selbst Vektoren usw. erzeugen; für einen der nächsten Schritte stellen wir hier noch zwei Möglichkeiten vor

    2.7.1 Sequenzen erstellen

    # erzeuge einen Vektor "s" mit den Zahlen von 1 bis 140
    s     <- seq(1, 140, 1)

    2.7.2 Werte wiederholen

    # erzeuge einen Vektor mit dem Wort "Liste1", das 140 Mal wiederholt wird
    t1    <- rep("Liste1",140)

    2.7.3 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))

    2.8 Dataframes manipulieren

    2.8.1 Spaltennamen ändern

    # 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

    2.8.2 Suchen und Ersetzen (einfach)

    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"

    • In Kapitel 7 (“Befehlsübersicht”) finden Sie noch eine andere Methode, wie man Werte suchen und ersetzen kann; wir empfehlen allerdings, dass Sie zuerst Kapitel 3 bis 5 durcharbeiten, bevor Sie diese Alternative ausprobieren

    2.8.3 Zwei Dataframes “mergen” (Infos rechts hinzufügen, nach Bedingung)

    • sehr häufig müssen Informationen zu einem Datenset ergänzt werden
    • im folgenden Beispiel wird eine Datei geladen (es entsteht ein Dataframe) und der Inhalt wird dem Inhalt eines vorhandenen Dataframe hinzugefügt; dabei werden zwei Bedingungen beachtet: in beiden Dataframes stimmt der Wert in der Spalte “subject_nr” überein; in beiden Dataframes stimmt der Werte in der Spalte “Trial_Index” überein
    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" ...

    2.9 Übung 1

    Teil 1

    Im ersten Teil der Übung führen Sie nur den angegebenen Code aus und beobachten, was dadurch geschieht.

    1. Erstellen Sie einen Vektor, in dem sich die Zahlen von 1 bis 9 5-mal wiederholen
    Vector1 <- rep(1:9, times = 5)
    1. Erstellen Sie einen Vektor, der aus den Zahlen 1 bis 45 besteht
    Vector2 <- rep(1:45)
    1. Erstellen Sie einen Vector, in dem die Buchstaben a, b, c 15-mal wiederholt werden
    Vector3 <- rep(c("a", "b", "c"), times = 15)
    1. Verbinden Sie alle drei Vektoren zu einem Dataframe mit dem Namen df1
    df1 <- data.frame(Vector1, Vector2, Vector3)
    1. Ändern Sie die Spaltenbezeichnungen zu „count“, „rt“, „subject”
    colnames(df1) <- c("count", "rt", "subject")
    1. Löschen Sie alle Vektoren, aber behalten Sie den dataframe und schauen Sie sich ihn an
    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

    • probieren Sie im Folgenden, das was Sie bisher gelernt haben mit dem Dataframe “pseudo_et_data” aus
    • die Übung besteht darin, dass Sie herausfinden, was die Befehle (“Code-Schnipsel”) im Folgenden bedeuten; was passiert, wenn Sie den Code verwenden?
    • probieren Sie auch aus, was passiert, wenn Sie die "" weglassen (siehe oben Datentypen)
    • Kopieren Sie den Code in eine Script-Datei und beschreiben Sie jeweils in einem Kommentar (“#”), was das jeweilige Kommando macht
    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

    • Ändern Sie außerdem alle Spaltennamen des Dataframe “df”

    Teil 4

    • Suchen und Ersetzen Sie die Zeichenkette “triangle” in der Spalte AOI in “Dreieck” im Dataframe “df”

    Zur Lösung

    3 Daten überprüfen

    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.

    3.1 Daten überprüfen

    3.1.1 Einfache Kreuztabellen

    • es ist wichtig, Daten hinsichtlich ihrer Konsistenz zu überprüfen, um Fehler bei der Auswertung zu vermeiden; dabei ist die “Qualitätskontrolle” gerade bei großen Datensätzen oft schwierig
    • um dennoch Datentabellen auf Vollständigkeit zu überprüfen, helfen uns Kreuztabellen, mit denen man zunächst ganz allgemein die Anzahl von Datenzeilen pro Bedingung ermitteln kann.
    • Eine Kreuztabelle ist in Zeilen und Spalten organisiert, in denen Zahlen zu finden sind.
    • Kreuztabellen lassen sich einfach mit dem Kommando “xtabs()” erzeugen
    • der Aufbau dieses Kommandos sieht folgendermaßen aus: xtabs(~ Variable1, df)
    • Was dieser “~” (tilde-Operator) bedeutet, wird im Rahmen des Tutorials nicht behandelt; für diejenigen, die fortgeschritten sind und mehr darüber erfahren wollen, suchen am besten nach “R Formula Method” im Internet
    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

    3.1.2 Komplexe Kreuztabellen

    • man kann auch mehrere Variablen kombinieren; in unserem Beispiel könnte uns interessieren, wie viele Datenzeilen es für jede Versuchsperson (“sub”) pro Bedinging (“condition”) gibt
    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
    • man kann auch noch mehr Variablen kombinieren
    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)
    • je mehr Variablen, desto unübersichtlicher
    • man kann Kreuztabellen natürlich auch als Objekte “abspeichern”

    3.1.3 Kreuztabellen als Dataframe

    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)
    • Achtung! das Objekt ist kein Dataframe
    • Falls man Kreuztabellen als Dataframe benötigt, kann man die Daten aber auch entsprechend abspeichern, nämlich mit “as.data.frame()”
    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 ...

    3.2 Varianz und Mittelwerte bestimmen (grob)

    3.2.1 Mittelwerte

    • Kreuztabellen geben nur an, wie viele Datenzeilen es gibt
    • in manchen Fällen ist es aber auch notwendig, Mittelwerte zu berechnen, um einen Überblick über die Daten zu bekommen (z.B. zur Kontrolle)
    • ein einfacher Weg ist “summary(df)”
    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  
    ##                                       
    ##                                       
    ## 
    • Beachten Sie wieder den Datentyp jeder Variable, denn nach dem Datentyp richtet sich, was summary() anzeigt; Sehen Sie den Unterschied zwischen “factors” und “integers”?
    • für factors wird Ihnen das angezeigt, was Sie bereits von der Verwendung von “xtabs” kennen; für integers (Zahlen) wird Ihnen der Mittelwert, der Median, der größte und der kleinste Wert und das erste und dritte Quantil angezeigt
    • Was sind Quantile? Um dies zu veranschaulichen, generieren wir eine einfache Grafik für die Variable “tot.dur”, eine Variable, die Dauer (Zeit) in Millisekunden erfasst
    boxplot(d$tot.dur, col=c('powderblue'))

    • Boxplots verraten auf einen Blick etwas über die Streuung der Daten
      • Median: Dicke schwarze Linie: dieser Wert teilt die Messwerte bei 50%; oberhalb liegen 50% der Datenpunkte und unterhalb liegen die anderen 50% der Datenpunkte
      • Quantile: Sie sehen eine Box; innerhalb dieser Box liegen 50% aller Daten; der obere Rand der Box markiert das dritte Quantil; 25% der Daten, die oberhalb des Median liegen; der untere Rand der Box markiert das erste Quantil; 25% der Daten, die unterhalb des Median liegen
      • Fühler: die übrigen horizontalen Striche geben jeweils den kleinsten und größten Wert an
    • mehr zur deskriptiben Statistik unter https://de.khanacademy.org/math/statistics-probability/summarizing-quantitative-data
    • Boxplots kann man auch pro Ausprägung einer anderen Variable erstellen; wir verwenden eine etwas andere Notation; diese Notation kennen Sie bereits von den Kreuztabellen
    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

    • Boxplots helfen also dabei, auf schnelle Art und Weise Daten und deren Streuung zu visualisieren
    • dadurch gelingt es zu überprüfen, ob es auffällige (unerwartete) Ergebnisse, von z.B. Reaktionszeiten, gibt

    3.2.2 Varianz

    • unter Varianz versteht man die quadrierte durchschnittliche Entfernung bzw. Abweichung vom Mittelwert
    • in der Forschung wird sie verwendet um zu erklären, warum es Unterschiede zwischen Versuchspersonen gibt (sog. “Varianzaufklärung”)
    • wegen der besseren Interpretierbarkeit wird jedoch meistens die Standardabweichung verwendet - diese wird aus der Wurzel der Varianz berechnet
    var(d$tot.dur) #Code für die Varianz
    ## [1] 93624.6
    sd(d$tot.dur) #Code für die Standardabweichung
    ## [1] 305.9814

    3.2.3 Normalverteilung

    • 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```

    • die Säulen geben die tatsächliche (“absolute”) Häufigkeit der gemessenen Werte an
    • die blaue Linie gibt an, wie die Häufigkeit der Werte verteilt sein müsste, damit man von Normalverteilung sprechen kann; in unserem Fall liegt wohl keine Normalverteilung vor, denn es gibt an den “Rändern” nicht weniger Daten als in der “Mitte”

    3.3 Übung 2

    1. Öffnen Sie das Datenset pseudo_et_data und nennen Sie es beliebig
    2. Erstellen Sie eine Kreuztabelle für die Spalte “AOI” und “sub” (an die Reihenfolge halten) und lassen Sie dann die Struktur der Kreuztabelle anzeigen
    3. Erstellen Sie eine Kreuztabelle für die Spalte “sub” und “condition” (an die Reihenfolge halten) und speichern Sie diese als df abspeichern. Lassen Sie dann die Struktur der Kreuztabelle anzeigen.
    4. Erstellen Sie Boxplots für jede einzelne Ausprägung der Variable “sub”, und zwar für die Werte der Variable “hits”

    Zur Lösung

    4 Deskriptive Statistik

    Kapitelübersicht
    In diesem Kapitel lernen Sie, wie Sie mithilfe des Pakets “plyr” und der Funktion SummarySE unterschiedliche Mittelwerte und Varianzen berechnen können.

    4.1 Vorbereitung

    Paket

    • stellen Sie sicher, dass das folgende Paket installiert und aktiviert ist
    library(plyr)

    Daten

    • Achtung!: Stellen Sie bevor Sie weitermachen sicher, dass Sie die Datei “test_data.csv” hier bereits runtergeladen und im Ordner “raw data” abgespeichert haben ; wir verwenden weiterhin die in Kapitel 1 vorbereitete Ordnerstruktur

    Funktion

    • Funktionen vereinen mehrere Kommandos und können auf x-beliebige Objekte angewendet werden; Funktionen sind also “kleine Helferlein”
    • Um eine Funktion nutzen zu können, muss sie R zur Verfügung gestellt werden; dabei lässt man den Code, der die Funktion definiert einmalig ausführen
    • das Schöne an Funktionen ist, dass Sie nicht wissen müssen, wie genau sie funktionieren, solange sie funktionieren!

    4.1.1 Die Summary SE-Funktion zum Berechnen von Mittelwerten und Varianz

    • es gibt eine sehr einfache Methode, schnell Mittelwerte und Varianz zu berechnen, nämlich mit der Summary SE-Funktion
    • der folgende Code führt keine Berechnungen aus (!), sondern definiert eine Funktion; wenn Sie den Code ausgeführt haben, steht die Funktion (im Environment) zur Benutzung zur Verfügung
    • es empfiehlt sich diesen Code in einem Skript abzuspeichern und jedes Mal, wenn man ihn braucht zu laden.
    ########### 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)
    }
    • nach dem Ausführen des Codes, steht die Funktion im “Environment” zur Verfügung

    • Achtung: Immer wenn Sie alle Objekte aus dem “Environment” löschen, löschen Sie auch die Summary SE-Funktion; in diesem Fall einfach neu laden

    4.2 Mittelwerte und Varianz

    • 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:

      • Grand Means: bei der Berechnung von Grand Means werden Daten zunächst nicht aggregiert; die Berechnung erfolgt unabhängig von Versuchspersonen und Items über alle Daten hinweg (Siehe Grafik)
      • Aggregated Data: es werden Durchschnittswerte pro VP und pro Item berechnet und dann davon Mittelwerte gebildet (Siehe Grafik)

    • Sie sehen, dass sich die Mittelwerte im Prinzip zwischen den verschiedenen Arten der Aggregation nicht unterscheiden, aber die Varianz

    • Warum unterscheidet sich die Varianz?

      • im aggregierten Datensatz werden die Mittelwerte auf Grundlage weniger Werte berechnet; extreme Werte (z.B. sehr groß wie 99 bei subject 1, oder sehr klein wie -3 bei subject 3) werden durch den ersten Schritt der Aggregation nivelliert
    • 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”)

    4.2.1 The power of the ddply

    • 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))

    4.2.2 Grand means mit ddply berechnen

    • Wir berechnen jetzt die Grand Means so wie in der Grafik oben und benutzen die Daten test_data.csv
    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
    • natürlich kann man, wie immer, die Ergebnisse als Objekt definieren, um sie später weiter zu verwenden
    • zusätzlich vergeben wir im Folgenden Namen für die berechneten Werte; wir nennen das Ergebnis von mean() “durchschnitt”, und das Ergebnis von sd() “SD” (s. folgenden Code)
    • um ein Objekt anzuzeigen tippen wir wie immer einfach den Namen des Objekts
    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

    4.2.3 subject- und item-aggregated means mit ddply berechnen

    • wir berechnen als nächstes die Mittelwerte pro Versuchspersonen und pro Items
    • Schauen Sie oben (bei dem Befehl str(d)) wie die Spalte für die Versuchspersonen und die Spalte für Items benannt ist
    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
    • als nächstes berechnen wir die “Mittelwerte der Mittelwerte” (siehe Grafik oben); wir verwenden die im letzten Schritt aggregierten Daten
    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

    4.2.4 Mit summarySE arbeiten

    • in manchen Situationen ist es einfacher die oben vorgestellte Funktion SummarySE zu verwenden
    • der Vorteil der Funktion besteht darin, dass Mittelwerte und verschiedene Maße für die Varianz ganz automatisch - ohne viel Code tippen zu müssen - ausgegeben werden
    • als Beispiel berechnen wir die Grand Means und die Mittelwerte auf der Grundlage der “By-subject”-aggregierten Werte
    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", ...))

    4.3 Übung 3

    • Berechnen Sie die Varianz aus derselben Datei “test_data.csv”. Hinweise: Bei ddply kann man mit var() die Varianz berechnen.
    • Berechnen Sie dann die unterschiedlichen Kennwerte (z.B. Mittelwert, Standardabweichung) aus dem R-eigenen Datensatz “iris”
    • Benutzen Sie zuerst ddply und dann die summarySE-Funktion; die Ergebnisse sollten bei beiden Methoden gleich sein

    Zur Lösung

    5 Visualisierung von Daten

    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.

    5.1 Paket “ggplot2”

    • Package “ggplot2” als mächtiges Werkzeug für die Datenvisualisierung
    • zunächst müssen Sie das Package installieren und aktivieren
    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

    • wir explorieren ggplot zunächst mit Hilfe des df “test_data.csv” aus dem letzten Kapitel
    • zur besseren Nachvollziehbarkeit nennen wir das importierte df “data”.
    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" ...

    5.2 Visualisierung von Daten, part 1

    • die einfachste visuelle Darstellung besteht im Plotten (= Grafik produzieren) aller Datenpunkte nach bestimmten Kriterien
    • beachten Sie die generelle Syntax beim Plotten mit ggplot
    • für die bessere Übersicht sollte der Code in unterschiedlichen Zeilen organisiert werden
      • in der ersten Zeile steht immer um welches Datenset und welche Variablen es sich beim Plotten handeln soll
      • in den nächsten Zeilen wird das Erscheinungsbild der Grafik definiert, inklusive Art der Grafik (z.B. Punkte oder Säulen) und Beschriftungen (Titel, Achsenbezeichnungen, etc.)
      • bei mehreren Zeilen Code, die zusammengehören verwendet man ein “+” um die Zusammengehörigkeit zu spezifizieren; das funktioniert übrigens auch bei vielen anderen Code-Schnipseln
    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

    • im Folgenden werden immer maximal drei Dinge im Vergleich zum ersten Plot geändert
    • zuerst fügen wir einen Titel hinzu
    • dann nutzen wir Farben
    • abschließend wird eine Einteilung nach der Variablen “VP” statt “Bedingung” vorgenommen
    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

    • wir sehen in dem letzten Plot ein Problem: die Variable “VP” ist vom Typ “integer” (siehe oben, str(data)); der Variablentyp erlaubt also Dezimalzahlen
    • das führt dazu, dass es in der Grafik so aussieht, als könnte es Versuchspersonen geben, die zwischen 1 und 2 bzw. 2 und 3 liegen (halbe Versuchspersonen sozusagen)
    • dasselbe Problem besteht für die Variable “Item”, für die als Datentyp auch “integer” angegeben ist
    • Lösung: wir geben in der ersten Zeile des Plots an, dass es sich bei der Variable “Item” um den Datentyp Faktor handelt
    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

    5.3 Plots, die Zusammenfassungen darstellen

    • um Zusammenfassungen direkt durch ggplot berechnen zu lassen, verwenden wir “stat_summary”
    • damit kann angegeben werden, was berechnet werden soll und wie die berechneten Werte dargestellt werden.
    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")

    • zur Überprüfung der Berechnung stellen wir als nächstes die summary und die Rohdaten in einem Plot dar, also eine Kombination des letzten und des ersten Plots
    • zusätzlich wird der Hintergund des Plots mit Hilfe einer Vorlage (Template) geändert; die Vorlage heisst “theme_bw”
    • außerdem sollen Rohdatenpunkte in grauer Farbe dargestellt werden & die summary Ergebnisse in rot
    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()

    • wie wäre es mit einem Säulendiagramm?
    • für die Optik definieren wir, dass die Säulen (engl. “Bar”) je nach Bedingung eingefärbt werden (“fill” statt “color”) in der ersten Zeile.
    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()

    5.4 Plots speichern

    • es gibt mehrere Möglichkeiten Plots zu speichern
    1. Über die Schaltfläche “Export”.
    2. Über einen Code-Schnipsel.

    • nachdem man auf “Export” geklickt hat, öffnet sich ein Fenster; in diesem kann man viele Einstellungen vornehmen

    • um Plots per Code zu speichern, verwendet man die Funktion “ggsave”
    • ggsave speichert den aktuellen (den als letztes produzierten) Plot in einem angegebenen Verzeichnis
    • zusätzlich kann man die Größe des Plots und die Auflösung spezifizieren
    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

    5.5 Plots “verschönern”

    • man kann bei der Verwendung von ggplot wirklich fast jeden Aspekt der Darstellung ändern, also die Farben, die Größe, man kann festlegen, was angezeigt werden soll und was nicht
    • um das alles zu lernen, empfehlen wir diese Website

    5.6 Visualisierung von Daten, part 2

    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.

    5.6.1 Über Gruppen (VP und Item) aggregieren und Daten plotten

    • zuerst laden wir alle libraries, die wir benötigen
    library(plyr)
    library(ggplot2)
    • dann benötigen wir unsere Testdaten
    Test_daten <- read.csv("./raw data/test_data.csv", sep=";") # wir laden das df test_data.csv und nennen es Test_daten

    5.6.2 Aggregieren mit ddply (bekannt aus Kapitel 4)

    • wir aggregieren die Daten über Versuchspersonen und Items und generieren jeweils ein eigenes Objekt
    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
    • jetzt benutzen wir die SummarySE-Funktion für die Berechnung der by subjects- und by items-aggregierten Daten
    sub_summary <- summarySE(sub_aggregated , measurevar="durchschnitt", groupvars=c("Bedingung"))
    itm_summary <- summarySE(item_aggregated , measurevar="durchschnitt", groupvars=c("Bedingung"))
    • wir betrachten die Ergebnisse
    • “Bedingung” gibt die Ausprägungen unserer Gruppenvariable (“groupvars” in der summarySE-Funktion) an
    • in der Spalte “durchschnitt”, unsere Messvariable (“measurevar” in der summarySE-Funktion), sehen wir den Mittelwert, der über die Werte aus dem aggregierten Datenset berechnet wurde
    • “sd” gibt die “Standardabweichung” an
    • “se” gibt den “Standardfehler” an
    • “ci” gibt die Konfidenzintervalle (95%) an
    • Zum Unterschied zwischen se, sd, und ci, hier mehr
    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

    5.6.3 Ergebnisse plotten

    • wir nutzen jetzt den Output der summarySE-Funktion, um verschiedene Grafiken mit ggplot zu erzeugen; dafür nutzen wir jedoch nicht die “stat_summary”-Funktion, die ggplot zur Verfügung stellt
    • anders gesagt, wir geben in ggplot, jeden Wert, der geplottet werden soll “per Hand” an, nämlich dadurch, dass wir ggplot zeigen, wo es nachschauen soll
    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()

    • als nächstes produzieren wir einen Barplot (Säulendiagramm), wobei wir für die Darstellung der Varianz auf die 95%-Konfidenzintervalle zurückgreifen
    • man sieht deutlich, wie die Werte für die “Fühler” berechnet werden: durchschnitt + ci und durchschnitt - ci. Die Werte für durchschnitt und ci werden aus dem Objekt “sub_summary” genommen
    • das ist das Objekt, das wir mit der summarySE-Funktion erstellt haben
    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()

    • Ja, die Ziffer in scale_y_continuous() hat sich von c(0, 130) auf c(30, 80) geändert. Mit der Funktion scale_y_continuous() können der minimale und maximale Wert in der y-Achse bestimmt werden.
    • zum Abschluss noch ein verschönerter Plot:
    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)

    6 Walkthrough Datenanalyse

    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.

    6.1 Schritt für Schritt Datenanalyse

    6.1.1 SET UP:

    1. Alle Rohdaten (.csv Dateien) in einem Ordner speichern (Ordnername Beispiel: „raw data“)
    2. Einen zweiten Ordner anlegen
    3. Den zweiten Ordner umbenennen: „METHOD_test“
    4. Den Ordner RAW in den Ordner METHOD_test verschieben
    5. Im Ordner METHOD_test noch einen Ordner anlegen, Name: „SKRIPTS“
    6. Im Ordner METHOD_test noch einen Ordner anlegen, Name: „PRE_PRO“
    7. Im Ordner METHOD_test noch einen Ordner anlegen, Name: „FINAL_DATA“
    8. Im Ordner METHOD_test noch einen Ordner anlegen, Name: „GFX“
    9. Im Ordner METHOD_test, gibt es jetzt also 5 Ordner
    10. RStudio öffnen
    11. Ein neues Projekt anlegen, ‚existing directory‘, bei ‚project workig directory‘, den Ordner METHOD_test auswählen; dann ‚create project‘ klicken
    12. Neue Skript-Datei erstellen; diese (leere) Skript-Datei abspeichern, und zwar im Ordner SKRIPTS, Name der Datei: „scr1“
    13. Gut, jetzt beginnt die Datenanalyse

    6.1.2 DATA LOADING:

    1. Code für das Data-Loading aus Kapitel 2 kopieren und in das Skript (scr1) einfügen
    2. Dateipfade anpassen, so dass sie auf den Ordner RAW verweisen, denn in diesem Ordner sind die zu ladenden Rohdaten
    3. Relevante Spalten aus den Output-Daten der Erhebungssoftware auswählen und im Skript angeben, es entsteht das Objekt „raw“

    6.1.3 DATA CHECKING

    1. Alle Mittel aus Kapitel 3 benutzen und die Daten auf Korrektheit checken; Z.B. sind alle Subjects enthalten? Ansonsten alles vollständig?
    2. Bei Fehlern, so lange Reparaturen vornehmen bis „raw“ vollständig ist
    3. Anweisungen aus Kapitel 2 zum Speichern verwenden, um das Objekt raw im Ordner PRE_PRO als .csv-Datei zu speichern, Name der Datei: proc_data.csv

    6.1.4 DESKRIPTIVE STATISTIK STEP 1

    1. Die Datei proc_data.csv mit dem Code aus Kapitel 2 laden, das Objekt soll „data“ heißen, „data“ dient jetzt als Grundlage für die Schritte 2, 3 und 4
    2. Mittelwerte und Varianz berechnen, Reaktionszeiten, Fehleranzahl, usw. so wie in Kapitel 4 beschrieben
    3. Alle interessanten Plots erstellen (siehe Kapitel 5)
    4. Interessante Grafiken speichern, und zwar im Ordner GFX
    5. Gibt es irgendwelche Auffälligkeiten? Große Datenstreuung? unplausible Ausreißer-Werte? Müssen die Daten noch einmal bereinigt werden?
    6. Wenn ja, dann die Daten weiterbearbeiten, Stichwort „subsets“
    7. Ein relevantes subset könnte sich zum Beispiel dadurch ergeben, dass Werte größer oder kleiner als eine bestimmte Reaktionszeit ausgeschlossen werden, oder dadurch, dass eine bestimmte Fehleranzahl nicht überschritten werden darf
    8. Den finalen Datensatz im Ordner FINAL_DATA speichern, Dateiname: final.csv

    6.1.5 DESKRIPTIVE STATISTIK STEP 2

    1. final.csv laden
    2. Schritte 2, 3, 4 von oben wiederholen, dabei nach Auffälligkeiten in Bezug auf die experimentellen Bedingungen achten
    3. Jetzt dokumentieren
    4. Die wichtigsten Ergebnisse in Form von 2-6 Grafiken darstellen

    Glückwunsch! Sie haben Ihren ersten Datensatz erfolgreich bearbeitet!

    7 Befehlsübersicht, Tipps und Tricks

    7.1 Objekte

    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"

    7.2 Pakete

    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")}

    7.3 Werte, Vektoren, Dataframes erstellen, löschen, umbenennen

    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!

    7.4 Spaltennamen ändern

    # Benenne die Spalten des df "add_info" um, und zwar in "index" und "Liste
    colnames(add_info) <- c("index","Liste")

    7.5 Auf Spalten, Zeilen und Werte zugreifen

    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 

    7.6 Subsets erstellen

    # 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.

    7.7 Subsets erstellen - vereinfachte Schreibweise

    # 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")), ]

    7.8 Datentabellen in R öffnen, speichern & laden

    # 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=";")

    7.8.1 Multiple Dateien laden

    • sehr oft liegen Daten in mehreren Dateien vor, zum Beispiel für jede Versuchsperson extra
    • mit dem folgenden Code ist es möglich, mehrere Dateien des Typs CSV auf einmal zu laden und zusammenzufügen
    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")

    7.9 2 Dateien mergen (zusammenführen)

    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

    7.10 Suchen und Ersetzen

    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","..."))

    7.11 Daten überprüfen mit Kreuztabellen

    # 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)

    7.12 Varianz, Mittelwerte & Normalverteilung

    wichtig: die Variablen müssen numerische Werte zurückgeben

    # einfache Varianzberechnung
    
    var(df$Variable1)
    
    # einfache Berechnung von Standardabweichung
    
    sd(df$Variable1)

    7.12.1 Einsetzen von library(plyr)

    # 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"))

    7.13 Plots

    7.13.1 ohne library

    # 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'))

    7.13.2 mit library(rcompanion)

    # Histogramm erstellen (z.B. um mit dem Auge auf Normalverteilung überprüfen)
    
    plotNormalHistogram(df$Variable1, col=c('powderblue'))

    7.13.3 mit library(ggplot)

    # 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)

    7.14 Package-Übersicht

    • plyr:

      • vereinfacht den Dateiaufteilungsvorgang, Dateibearbeitungsvorgang und Dateibereinigungsvorgang
    • readr:

      • hilft Dateien aus z.B. einem csv-File zu laden
    • rcompanion:

      • ein Histogramm gibt an wie häufig bestimmte Werte vorkommen
      • wir benutzen ein Kommando aus dem Paket (library) “rcompanion”
    • ggplot2:

      • Mächtiges Werkzeug für die Datenvisualisierung. oft sind Berechnungen schon vor der eigentlichen Visualisierung nötig (mehr dazu im Kapitel 6)
    • RColorBrewer:

      • erstellt Farboptionen für ggplot2
    • Verwendete Pakete müssen immer zitiert werden, wenn Sie Ihr Skript in Ihre Arbeit einfügen wollen.

    • Wie findet man die richtige Zitation heraus?

      • Man kann mit citation() die richtige Zitation eines Pakets anzeigen lassen
    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},
    ##   }

    7.15 Verwendete Funktionen

    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
    }

    7.16 Verwendete Datensätze

    7.17 Data

    7.18 Dataset

    8 Lösungen für Übungen

    8.1 Übung 1 (Kapitel 2)

    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)

    8.2 Übung 2 (Kapitel 3)

    1. Öffnen Sie das Datenset pseudo_et_data und nennen Sie es beliebig
    d <- read.csv("./raw data/pseudo_et_data.csv", sep=";")
    1. Erstellen Sie eine Kreuztabelle für die Spalte “AOI” und “sub” (an die Rheinfolge halten) und lassen Sie dann die Struktur der Kreuztabelle anzeigen
    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)
    1. Erstellen Sie eine Kreuztabelle für die Spalte “sub” und “condition” (an die Rheinfolge halten) und speichern Sie diese als df abspeichern. Lassen Sie dann die Struktur der Kreuztabelle anzeigen.
    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 ...
    1. Erstellen Sie Boxplots für jede einzelne Ausprägung der Variable “sub”, und zwar für die Werte der Variable hits
    boxplot(hits ~ sub, data = d)

    8.3 Übung 3 (Kapitel 4)

    • Berechnen Sie die Varianz aus derselben Datei “test_data.csv”. Hinweise: Bei ddply kann man mit var() die Varianz berechnen.
    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