7  Diagnostische Visualisierung der Rohdaten

Zeitplanung: Abbildungen der Rohdaten sind ein elementarer Teil von Plausibilitäts-Checks. Man sollte sich sofort damit befassen, wenn man die Daten hat. Sobald Sie einen vollständigen Datensatz einer Vp haben, können Sie den Code für die Abbildung von Einzel-Vp-Daten programmieren. So nutzen Sie optimal die Erhebungszeit schon für Programmier- und Auswertungsarbeiten.

7.1 The “Grammar of Graphics”

Wir plotten in R Daten mit dem Package ggplot2. Dieses Package basiert auf der sog. “Grammar of Graphics”. Diese ist ausführlich von Hadley Wickham (Wickham 2009) beschrieben und sprengt den Rahmen dieses Dokuments.

Das Wichtigste zur Grammar of Graphics im Kontext dieses Buches ist:

  • Die Eigenschaften des Plots nennt man “Aesthetics”
  • Beispiele für Aesthetics sind:
    • x- und y-Richtung
    • Farbe von Elementen
    • Form(en) der Elemente
    • Größe der Elemente
    • Linienart für Verbindungen zwischen Elementen (Farbe, gepunktet, gestrichelt, Dicke… )
  • Beispiele für Eigenschaften der Daten sind typischerweise Ausprägungen von (diskreten oder kontinuierlichen) Variablen, z.B.:
    • Eine kontinuierliche AV Variable wie Reaktionszeit
    • Eine diskrete AV wie Antwort korrekt (ja/nein)
    • Eine diskrete UV, wie ein Bedingungs-Faktor
  • In Datenvisualisierungen (Plots) werden dann Eigenschaften aus den Daten auf bestimmte Eigenschaften des Plots “gemappt” (aesthetic mapping). Z.B. werden Datenpunkte anders eingefärbt (=> Ploteigenschaft), je nachdem zu welcher Bedingung (Dateneigenschaft) sie gehören
  • Die strenge Auslegung der Grammar of Graphics bedeutet, dass man eine Eigenschaft der Daten auf eine Aesthetic des Plots mappt. Man würde also zum Beispiel die RTs auf die y-Achse des Plots “mappen” und die Bedingung (sagen wir “crossed” vs. “uncrossed”) als Farbe ausdrücken aber man würde nicht RTs sowohl in y-Position wie auch im Farbton ausdrücken. Diese Regel wird aber häufig ignoriert. Z.B. passen viele Leute sowohl Farbe als auch Form und Linienart an die Faktorstufen an, obwohl laut Regel nur eine Sache im Plot angepasst werden sollte. Die Grammar of Graphics ist ein System, dem man folgen kann oder halt auch nicht. Manchmal ist es aber gut zu wissen, dass ggplot auf diesem Systerm basiert, weil es helfen kann zu verstehen, warum der Output von ggplot so ist wie er ist.
  • Man sollte Mapping konsistent verwenden. d.h. auch über Plots hinweg. Entsprechend sollte man sollte nicht in Abbildung 1 die Bedingung als Farbe und in Abbildung 2 die Bedingung plötzlich als Form ausdrücken. Man soll also lieber konsistent als kreativ sein.

7.2 Visualisierung von Rohdaten pro Vpn

Wir prüfen jetzt noch einmal, ob die Daten plausibel sind - diesmal nicht anhand von Zahlen, sondern anhand der Abbildung. Was das bedeutet, haben wir im letzten Teil beschrieben. Wir besprechen zunächst, wie man die Grafik erstellt und danach, wie man sie interpretiert.

7.2.1 Visualisierung der AV Antworten

Welche Art von Plot man macht, hängt von Designs und Stichprobe ab. Da wir ein within-subject Design mit einer relativ kleinen Stichprobe (19 nach Enfernung von 2 Vpn) haben, bietet es sich sich, einzelne Plots für die Personen zu machen. Dies geht mit der “facets”-Funktion von ggplot2.

Zunächst berechnen wir pro Vpn denn Prozentsatz richtiger Antworten. Es bietet sich an, für komplexere Plots einen eigenen Datensatz zu erstellen. Wir nennen diesen “dp” (für data plot).

dp <- dc %>% 
  group_by(participant, factor_A, factor_B, posture, SOA) %>% 
  summarise(percCorr=mean(respClean)*100)
`summarise()` has grouped output by 'participant', 'factor_A', 'factor_B',
'posture'. You can override using the `.groups` argument.
ggplot(dp, aes(x=SOA, y=percCorr, shape=factor_A, linetype=factor_B, color=posture)) +
  geom_point() +
  geom_path(aes(group=interaction(participant, factor_A, factor_B, posture))) +
  facet_wrap(~participant)

Anteil korrekter Antworten für jede Vp

Das erklärte “Mapping” von Daten auf “Aesthetics” ist (vor allem) in der ersten Zeile des Plot-Befehls in der Funktion “aes” zu sehen. Etwas komplexer ist der Befehl innerhalb von “geom_path”, welches was Linien zeichnet. Der group Parameter definiert, welche Beobachtungen zusammen eine Gruppe ergeben. Mit “interaction” sagt man hier, dass die Gruppe die Kombination betrifft aus den genannten Faktoren. Das sind in dem Fall alle außer SOA. Da wir das SOA auf der x-Achse abtragen (x=SOA), wird mit diesem aes() für jede Faktorenkombination ein Element pro SOA gezeichnet. Die Linien verbinden alle SOAs derselben Gruppe miteinander. Die Form des Elements bezeichnet die Faktorstufe des Faktors A; die Linie bezeichnet die Stufe des Faktors B. Die Farbe bezeichnet, ob die Hände (un)gekreuzt gehalten wurden. Jede Dateneigenschaft ist also auf genau eine Ploteigenschaft gemappt.

Der Plot zeigt sofort einige Dinge, von denen wir bisher gar nichts wussten. Das Wichtigste:

  • VP 16 und 27 sind in den crossed Bedingungen in ihrer Performance verdächtig nahe an 50% (der Ratewahrscheinlichkeit). Da sie aber in den anderen Bedingungen gut performen und auch bei längeren SOA besser sind, gehen wir davon aus, dass sie instruktionskonform agiert haben, aber einfach diese Bedingungen sehr schwer fanden (einen besonders starken crossing effect zeigten). Wir belassen diese Personen daher in unserer Analyse.
  • VP 23 hat Leistungen von fast 0 Prozent. Das ist praktisch unmöglich bei einer Ratewahrscheinlichkeit von 50%. Es würde ja bedeuten, dass die Person exakt entgegengesetzt den Instruktionen gedrückt hat und darin sogar sehr gut war. Es ist sehr wahrscheinlich, dass die Knöpfe falschrum angeschlossen oder hingelegt wurden oder die Instruktion umgekehrt war als sie sollte. Da wir das aber nur aus dem Protokoll entnehmen könnten, welches uns hier nicht vorliegt, entfernen wir diese Vp.
dc <- dc %>% filter(participant != "B006b-23")
dc$participant <- droplevels(dc$participant)

7.2.2 Visualisierung der AV RTs

Als nächstes machen wir einen ähnlichen Plot für die Reaktionszeiten.

dp <- dc %>% 
  group_by(participant, factor_A, factor_B, posture, SOA) %>% 
  summarise(meanRT=mean(rtClean))
`summarise()` has grouped output by 'participant', 'factor_A', 'factor_B',
'posture'. You can override using the `.groups` argument.
ggplot(dp, aes(x=SOA, y=meanRT, shape=factor_A, linetype=factor_B, color=posture)) +
  geom_point() +
  geom_path(aes(group=interaction(participant, factor_A, factor_B, posture))) +
  facet_wrap(~participant)

Reaktionszeiten für jede Vp

7.3 Visualisierung auf Gruppenebene

Als nächstes wollen wir die Daten über die Stichprobe gemittelt plotten.

Wir gehen ähnlich vor wie oben, lassen aber “participant” sowohl bei dem “group_by” wie auch in den “facet_wrap” weg. Nun mitteln tidyverse und ggplot über alle Daten und teilen nicht mehr in verschiedene Versuchspersonen ein.

Hinweis: wann was mitteln?

Wenn alle Vpn gleich viele Trials absolviert haben, ist es egal, ob man…

  • erst pro Vp mittelt und dann die Mittelwerte aller Vpn mittelt als Gruppenmittel, oder
  • alle Trials direkt zusammenmittelt.

Dies ist aber nicht der Fall, wenn sich die Trialzahlen zwischen den Vpn unterscheiden. Mittelt man alle Trials direkt zusammen, gehen Vpn mit weniger Trials auch weniger in den Mittelwert ein. Dies liegt daran, dass der Mittelwert berechnet wird als Summe_aller_Trials/Zahl_aller_Trials. Ermittelt man hingegen zunächst einen Mittelwert pro Vp und erst anschließend das Mittel aller Vps, geht jede Vp in gleichem Maße ein, da der Stichprobenmittelwert berechnet wird als Summe_individueller_Mittelwerte/Zahl_der_Vpn.

Bei kleinen Unterschieden in den Trialzahlen, wie sie sich bei uns durch das Rausschmeißen mit 2 s.d. ergeben haben, wird man zwischen diesen beiden Varianten auf einer Abbildung keinen Unterschied sehen. Für das Berechnen von Statistiken kann es aber natürlich relevant sein. Welche Form der Mittelung die richtige ist, ist übrigens umstritten: viele gehen davon aus, dass jede Vp gleich stark eingehen sollte; es spricht aber auch etwas dafür, dass eine Vp, von der weniger Daten vorliegen, geringer gewichtet wird.

7.3.1 AV Antwort

dp <- dc %>% 
  group_by(factor_A, factor_B, posture, SOA) %>% 
  summarise(percCorrect=mean(respClean)*100)
`summarise()` has grouped output by 'factor_A', 'factor_B', 'posture'. You can
override using the `.groups` argument.
p1 <- ggplot(dp, aes(x=SOA, y=percCorrect, shape=factor_A, linetype=factor_B, color=posture)) +
  geom_point() +
  geom_path(aes(group=interaction(factor_A, factor_B, posture)))
p1

Anteil korrekter Antworten in der Gruppe

In dieser Abbildung können wir einiges erkennen, z.B.:

  • dass “crossed” zu mehr Fehlern führt
  • dass bei Faktor_B vor allem “Level_2” zu mehr Fehlern führt
  • dass Faktor_A weniger auszumachen scheint

Das sind natürlich erstmal nur deskriptive Beobachtungen. Ob diese Effekte statistisch signifikant sind, wird man erst nach der Statistk sagen können.

7.3.2 AV RT

Zuletzt schauen wir uns noch die RT Daten an.

dp <- dc %>% 
  group_by(factor_A, factor_B, posture, SOA) %>% 
  summarise(meanRT=mean(rtClean))
`summarise()` has grouped output by 'factor_A', 'factor_B', 'posture'. You can
override using the `.groups` argument.
p2 <- ggplot(dp, aes(x=SOA, y=meanRT, shape=factor_A, linetype=factor_B, color=posture)) +
  geom_point() +
  geom_path(aes(group=interaction(factor_A, factor_B, posture)))
p2

Miittlere RTs in der Gruppe

Hier kann man deskriptiv sehen, dass das Effektmuster bei den RT genau umgekehrt ist als bei den Antworten. Bei crossed und bei Level_2 von factor_B sind die Antworten langsamer. Dieses inverse Muster macht Sinn, denn die Bedeutung von RT und %korrekt ist entgegengesetzt: je besser die Vp die Aufgabe macht, desto kleiner ist die RT (=schnell), aber desto größer ist die Zahl richtiger Trials (=hohe Prozentwerte).

Geschafft!

Es ist jetzt alles in Ordnung. Wir können nun mit der Statistik beginnen.

7.4 Daten abspeichern

Jetzt nachdem wir einige Änderungen an den Daten vorgenommen haben in den letzten vier Kapiteln und damit das Datenscreening beendet ist, macht es Sinn, die Daten unter einem neuen Datensatz abzuspeichern. So kann man die vorverarbeiteten Daten in Skripten, die man für die Statistik schreibt, leicht wieder laden und mzss nuicht alle Befehle nochmal laufen lassen. Wir nennen den neuen Datensatz mal “RTL_beispieldaten_clean.RData”.

save(dc, ds, file = "RTL_beispieldaten_clean.RData")