Teaser: Datenanalyse mit R

Seminar Experimentelles Forschungsdesign

Autor:in
Zugehörigkeit

Marko Bachl

Freie Universität Berlin

Veröffentlichungsdatum

01. 07. 2024

Einführung

Dieses interaktive Dokument bietet einen ersten Einstieg in die Datenanalyse mit R. Der Code ist in R geschrieben und wird mit WebR im Browser ausgeführt. Das Format eignet sich gut zur Einführung, da Sie nichts installieren müssen und die Ausführung selbst auf (halbwegs aktuellen) Smartphones und Tablets möglich ist.

Wenn Sie tiefer in die Datenanalyse mit R einsteigen möchten, empfehle ich Ihnen die Installation von R und RStudio auf einem lokalen Rechner. Dies ist sinnvoll, da Sie in der WebR-Anwendung lokale Dateien nicht direkt einlesen und den erstellten Code nicht direkt speichern können. Zum Einstieg finden Sie ein R-Skript mit den hier präsentierten Code-Ausschnitten in Blackboard🔒 im Ordner Datenanalyse.

In dieser einzelnen Seminarsitzung können wir nur absoluten Grundlagen besprechen, die Sie zur Analyse der Daten aus Ihrer Experimentalstudie benötigen. Wenn Sie am IfPuK tiefer in die Datenanalyse einsteigen möchten, können Sie in einem der nächsten Semester den Kurs Datenanalyse mit R von Dr. Lück-Benz besuchen. Unter dem ersten Link finden Sie das gesamte Kursmaterial, sodass Sie sich auch eigenständig einarbeiten können. Darüber hinaus finden Sie im Internet unzählige Ressourcen aller Art, die Ihnen bei der Einarbeitung in R helfen können. Für jeden Geschmack, Lerntyp, und jedes Vorwissen ist etwas dabei.

Hinweise zur Benutzung dieses interaktiven Dokuments

  • Wenn Sie den vorgegebenen Code einfach ausführen möchten, klicken Sie auf den Play-Button (“Run Code”).
  • Die Code-Felder sind interaktiv, dass heißt, Sie können den Code verändern und erneut ausführen.
  • Die Schritte des vorgegebenen bauen aufeinander auf:
    • Sie müssen die vorherigen Schritte durchführen, um die nachfolgenden Schritte ausführen zu können.
    • Wenn Sie den Code in einem Schritt verändern, müssen Sie ggf. die nachfolgenden Schritte ebenfalls anpassen und erneut ausführen.

Pakete laden

R ist eine Programmiersprache, die durch Pakete erweitert werden kann. Pakete enthalten Funktionen, die spezielle Aufgaben erledigen. In diesem Dokument verwenden wir die Pakete dplyr, janitor und ggplot2. Die Pakete dplyr und janitor enthalten Funktionen, die das Arbeiten mit Daten erleichtern. Das Paket ggplot2 enthält Funktionen zum Erstellen von Grafiken. Darüber hinaus verwenden wir Funktionen aus base und stats, die in R standardmäßig enthalten sind.

Zusätzliche Pakete müssen vor der erstmaligen Verwendung mit der Funktion install.packages() installiert werden. In diesem Dokument sind die Pakete bereits installiert und können direkt geladen werden. Dies geschieht mit der Funktion library().

In R steht jeder Befehl in einer eigenen Zeile.

Daten einlesen

Zuerst müssen die Daten eingelesen werden. Hierzu verwenden wir die Funktion read.csv2(). Diese Funktion liest Daten aus einer CSV-Datei ein, in der die Spalten mit ; getrennt sind. Die Daten werden in einem data.frame gespeichert. Ein data.frame ist eine Tabelle, die aus Zeilen und Spalten besteht. Jede Spalte enthält eine Variable (bei uns: die Antwort auf eine Frage), jede Zeile enthält einen Fall (bei uns: eine Versuchsperson).

Wir speichern den Datensatz in einem Objekt mit dem Namen daten. Das geschieht mit dem sogenannten Zuweisungsoperator. In R können Sie dafür das Zeichen = oder <- verwenden.

Ich habe die Daten bereits aus Sosci Survey exportiert und aufbereitet. Sie können die Daten daher direkt über einen Link einlesen. Sie finden die Datensätze hier: https://bachl.github.io/raw_data/.

Fügen Sie den Link zur CSV-Datei Ihrer AG in die Funktion read.csv2() ein. Der Link muss in Anführungszeichen stehen. Führen Sie dann den Code aus.

Daten ansehen

Wenn wir ein Objekt in R ansehen wollen, können wir einfach dessen Namen in die Konsole eingeben. Das funktioniert auch mit data.frame-Objekten. Geben Sie den Namen des Objekts, daten, in die folgende Konsole ein und führen Sie den Code aus.

Wir können zwar erahnen, wie dieser Datensatz aufgebaut ist. Allerdings ist der Datensatz viel zu groß, um ihn sinnvoll in einem Fenster anzuzeigen. Daher verwenden wir die Funktion str(), um uns die Struktur des Datensatzes anzeigen zu lassen.

Ändern Sie Befehl in der Konsole, indem Sie die Funktion str() ergänzen, sodass der Name des Objekts innerhalb der Klammer steht. Führen Sie dann den Code nochmals aus.

Wir sehen nun die Zahl der Fälle (“obs.”, Zeilen im Datensatz) und der Variablen (“variables”, Spalten im Datensatz). Darüber hinaus sehen wir die Namen der Variablen und deren Datentypen. Die Datentypen sind wichtig, da sie bestimmen, welche Operationen auf den Variablen durchgeführt werden können. Mit int (Integer, Ganzzahl) und num (Numeric, Dezimalzahl) können wir rechnen. Variablen vom Typ chr (Character, Zeichenkette) können wir nur auszählen. Zudem sehen wir die Ausprägungen der Variablen in den ersten Fällen. NA steht für “Not Available” und bedeutet, dass in dieser Zelle kein Wert steht — z.B., weil die Frage nicht beantwortet wurde.

Die Variablen habe ich so benannt, dass Sie in den Namen (hoffentlich) die Fragen aus Ihrer Studie wiedererkennen. Die Bedeutungen der Ausprägungen der numerischen Variablen können Sie in Sosci Survey nachschlagen, indem Sie die entsprechende Frage aufrufen.

Eine Variable auszählen

Wir beginnen mit einer einfachen Analyse: Wir zählen die Ausprägungen einer Variable. Dazu verwenden wir die Funktion tabyl() aus dem Paket janitor. Die Funktion benötigt zwei Argumente: den Datensatz und den Namen der Variable, die wir zählen möchten: tabyl(DATENSATZ_HIER, VARIABLE_HIER)

Beginnen wir nun mit der Beschreibung unserer Stichprobe. Zuerst zählen wir die Ausprägungen der Variable gender. Fügen Sie die Namen des Datensatzes und der Variable in die Funktion tabyl() ein und führen Sie den Code aus.

Wenn alles funktioniert hat, sehen wir nun die Verteilung des Geschlechts in unserer Stichprobe. Unter gender sehen wir die Ausprägungen der Variable. Unter n sehen wir die Anzahl der Fälle, die diese Ausprägung haben. Unter percent sehen wir den Anteil der Fälle an allen Fällen. valid_percent zeigt den Anteil der Fälle an den Fällen, die eine gültige Antwort gegeben haben.

Standardmäßig ist die Tabelle in alphabetischer Reihenfolge der Ausprägungen sortiert. Mit der Funktion arrange() aus dem Paket dplyr können wir die Tabelle nach einer anderen Variable sortieren. Die Funktion arrange() benötigt zwei Argumente: den Datensatz und den Namen der Variable, nach der sortiert werden soll. Der Datensatz, den wir sortieren wollen, ist die Ausgabe der Funktion tabyl(). Wir könnten daher die Funktion arrange() um die Funktion tabyl() herum schreiben: arrange(tabyl(daten, gender), n), um die Ausprägungen nach Häufigkeit zu ordnen.

Übersichtlicher ist für solche Kombinationen der sogennante Pipe-Operator, |>. Er gibt die Ausgabe einer Funktion an die nächste Funktion weiter, wo diese in der Regel als erstes Argument verwendet wird. Dadurch entsteht recht gut lesbarer Code, da |> als “und dann” gelesen werden kann. Wir schreiben also: tabyl(daten, gender) |> arrange(n).

Fügen Sie |> arrange(n) zum Befehl in der Konsole hinzu und führen Sie den Code aus. Mit |> können wir übrigens Befehle über mehrere Zeilen verteilen, was der Lesbarkeit zugute kommt.

Wenn wir die Tabelle lieber nach absteigender Häufigkeit sortieren wollen, können wir die Funktion desc() aus dem Paket dplyr verwenden. desc() benötigt ein Argument: die Variable, nach der absteigend sortiert werden soll.

Fügen Sie desc(n) zum Befehl in der Konsole hinzu und führen Sie den Code aus.

Zählen Sie die Ausprägungen der Variablen insta (Instagram-Nutzung), edu (Bildung) und grp (Gruppenzuordnung im Experiment) aus.

Sie können mehrere Befehle nacheinander in derselben Konsole eingeben und ausführen. Dann sehen Sie alle Ergebnisse im Überblick.

Maßzahlen berechnen

Neben der Häufigkeit von Ausprägungen können wir auch Maßzahlen wie z.B. Mittelwert oder Standardabweichung berechnen. Dazu verwenden wir die Funktion summarise() aus dem Paket dplyr. Die Funktion summarise() benötigt zwei Argumente: den Datensatz und die Berechnung, die wir durchführen möchten. Die Berechnung wird in der Form Variable = Funktion(Variable) angegeben.

Typische Maßzahlen und ihre Funktionen in R:

  • Mittelwert: mean()
  • Median: median()
  • Standardabweichung: sd()

Diese Funktionen benötigen als Argumente die Variable, für die die Maßzahl berechnet werden soll. Außerdem haben sie das Argument na.rm, mit dem wir festlegen können, ob fehlende Werte ignoriert werden sollen. Mit na.rm = FALSE, der Voreinstellung, wird NA zurückgegeben, wenn mindestens ein Fall einen fehlenden Wert hat. Mit na.rm = TRUE wird der fehlende Wert ignoriert und die Maßzahl berechnet.

So berechnen wir z.B. den Mittelwert, Median und die Standardabweichung des Alters. Wir müssen beachten, dass nicht alle Versuchspersonen alle Fragen beantwortet haben. Daher setzen wir na.rm = TRUE. In der letzten Zeile berechnen wir die Anzahl der gültigen Fälle.

sum(!is.na(age)) lässt sich so verstehen: is.na(age) gibt TRUE zurück, wenn age fehlend ist, und FALSE, wenn age fehlend ist. ! bedeutet “not” (nicht), dreht diese Werte also um; sum() zählt die TRUE-Werte.

Häufig wollen wir Maßzahlen für verschiedene Gruppen berechnen. Dazu können wir die Funktion group_by() aus dem Paket dplyr verwenden. group_by() benötigt zwei Argumente: den Datensatz und die Variable, nach der gruppiert werden soll. Die Funktion summarise() berechnet dann die Maßzahlen für jede Gruppe. group_by() lässt sich sehr gut mit dem Pipe-Operator |> in eine bestehende Auswertung einfügen.

Fügen Sie group_by(gender) |> in Zeile 2 ein und führen Sie den Code erneut aus.

Vergleichen Sie die Altersverteilung age zwischen den Experimentalgruppen grp. Hier sollte sich (hoffentlich) kein relevanter Unterschied zeigen.

Fälle auswählen

Manchmal wollen wir eine Analyse nur mit Versuchspersonen durchführen, die bestimmte Kriterien erfüllen. Dazu können wir die Funktion filter() aus dem Paket dplyr verwenden. filter() benötigt zwei Argumente: den Datensatz und die Bedingung, die erfüllt sein muss. Die Bedingung wird in der Form Variable == Wert angegeben. Typische Operatoren sind == (gleich), != (ungleich), > (größer), < (kleiner), >= (größer oder gleich), <= (kleiner oder gleich). Mit & (und) und | (oder) können wir Bedingungen mehrere verknüpfen.

filter() lässt sich ebenfalls sehr gut mit dem Pipe-Operator |> in eine bestehende Auswertung einfügen.

Fügen Sie filter(age >= 21) |> in Zeile 2 ein und führen Sie den Code erneut aus, um nur Versuchspersonen ab 21 Jahren zu betrachten.

Solche Filter können wir in der Analyse einsetzen, wenn wir in Ihrer Präregistrierung bestimmte Ausschlusskriterien für Ausreißer festgelegt haben (Voraussetzung für den registrierten Hypothesentest) oder wenn wir neugierig sind, ob sich die Ergebnisse in bestimmten Teilgruppen unterscheiden.

Vergleich der Experimentalgruppen

Alle Arbeitsgruppen haben sich für numerische abhängige Variablen entschieden. Daher können wir den Unterschied zwischen den Gruppenmittelwerten als Schätzung für den Effekt des Treatments verwenden.

Eine Möglichkeit, die Gruppenmittelwerte deskriptiv (in der Stichprobe) zu vergleichen, haben wir bereits kennen gelernt: die Funktionen group_by() und summarise(). Wenn wir die Analyse nach grp gruppieren, erhalten wir die Maßzahlen für jede Gruppe.

Suchen Sie den Namen einer abhängige Variable aus dem Datensatz (Funktion str()) und fügen Sie ihn unten ein. Führen Sie den Code aus, um ein erstes Ergebnis Ihres Experiments zu sehen!

Für den Hypothesentest wollen wir aber nicht nur wissen, ob sich die Mittelwerte in der Stichprobe unterscheiden. Wir wollen prüfen, ob der Unterschied zwischen den Gruppen statistisch signifikant ist. Um Mittelwerte in zwei Gruppen zu vergleichen, verwenden wir den t-Test. Er wird mit der Funktion t.test() durchgeführt.

t.test() benötigt drei Argumente:

  • die abhängige Variable und die Gruppenvariable in der Form abhaengige_variable ~ gruppen_variable
  • den Datensatz
  • das Argument alternative mit den Werten "two.sided", "greater" oder "less", um den Test einseitig oder zweiseitig durchzuführen.
    • "two.sided": zweiseitiger Test; Hypothese: \(M_1 \neq M_2\); Null-Hypothese: \(M_1 = M_2\)
    • "greater": einseitiger Test; Hypothese: \(M_1 > M_2\); Null-Hypothese: \(M_1 \leq M_2\)
    • "less": einseitiger Test; Hypothese: \(M_1 < M_2\); Null-Hypothese: \(M_1 \geq M_2\)

Einseitige Tests haben größere statistische Power, dürfen aber nur durchgeführt werden, wenn wir in der Präregistrierung eine gerichtete Hypothese angekündigt haben. Ideal wäre es, wenn in der Präregistrierung der einseitige Test explizit angekündigt wurde.

Wenn die Gruppenvariable wie in unserem Fall eine Zeichenkette ist, werden die Gruppen alphabetisch sortiert. Wenn Sie sich nicht mehr sicher sind, wie die Ausprägungen der Gruppenvariable benannt sind, können Sie noch einmal tabyl() verwenden.

Fügen Sie nun die Namen der abhängigen Variable und des Datensatzes sowie die Richtung des Tests in die Konsole ein und führen Sie den Code aus, um den t-Test durchzuführen.

Die Ausgabe des t-Tests zeigt:

  • abhängige Variable und Gruppenvariable
  • Empirischer t-Wert, Freiheitsgrade und daraus abgeleiteter p-Wert
  • Richtung des Tests (Formulierung der Alternativhypothese)
  • 95%-Konfidenzintervall für den Unterschied der Mittelwerte
  • Gruppenmittelwerte in der Stichprobe

Mit diesen Angaben können wir unsere Hypothese testen. Wir entscheiden, ob wir unsere Hypothese beibehalten dürfen (die Hypothese wird von den Daten gestützt) oder sie verworfen werden muss.

Wenn wir den Test mit einem Teildatensatz durchführen wollen, bietet sich die Schreibweise mit dem Pipe-Operator |> an. Da der Datensatz das dritte Argument der Funktion ist, müssen wir ihn mit _ angeben. In der Konsole können Sie in Zeile 2 beliebige Filter ergänzen.

Führen Sie nun die Tests aller in der Präregistrierung genannten Hypothesen durch.

Überlegen Sie sich zudem, welche Analysen zusätzlich interessant sein könnten. Führen Sie diese durch oder fragen Sie mich, wenn Sie nicht genau wissen, wie Sie dabei vorgehen sollen.

Grafiken erstellen

ggplot2 ist ein sehr mächtiges Paket zum Erstellen von Grafiken. In dieser Einführungsstunde können wir nur die absoluten Grundlagen besprechen. Das Paket ist in ggplot2: Elegant Graphics for Data Analysis dokumentiert. Hier finden Sie nur ein Beispiel, um den Mittelwertvergleich zwischen den Experimentalgruppen darzustellen. Sie können die entsprechenden Variablen einfügen und die Beschriftungen ändern, um Abbildungen für die Abschlusspräsentation zu erstellen.

Zusätzliche Konsole