9  Verknüpfung von Antworten und Reaktionszeiten in ein Maß

9.1 Speed-Accuracy-Tradeoff

Der Zusammenhang von den in der kognitiven Psychologie typischen Verhaltensmaßen Reaktionszeit und (Korrektheit von) Antworten ist ein seit vielen Jahrzehnten viel diskutiertes Thema. Grundsätzlich ist die Idee, dass schwierige Kognitive Prozesse erstens länger dauern und zweitens zu mehr Fehlern führen. Demnach ist zu erwarten, dass eine höhere Anzahl an Fehlern auch mit längeren RTs einhergeht.

Speed-Accuracy-Tradeoff

Dieser Gedanke übersieht allerdings, dass sich Reaktionszeit und Fehlerhäufigkeit auch strategischen gegeneinander austauschen lassen.

  • Eine Person könnte zum Beispiel sich mehr Zeit lassen beim Antworten mit dem Ziel möglichst wenig Fehler zu machen.

  • Eine andere Person könnte riskanter vorgehen und versuchen möglichst schnell zu antworten und dabei in Kauf zu nehmen, dass sie mehr Fehler macht.

Dieses Phänomen, dass sozusagen Genauigkeit (wenig Fehler machen) gegen Geschwindigkeit “eingekauft” werden kann, wird als Speed-Accuracy-Tradeoff bezeichnet.

… Besonders blöd (für die Auswertung von Experimenten) ist der Trade-off, wenn Versuchspersonen zwischen Bedingungen verschiedenen Strategien anwenden.

  • Zum Beispiel könnte eine Vp bei einer leichten Kontrollbedingung sehr schnell vorgehen und ab und zu Flüchtigkeitsfehler machen; in einer schwierigen Versuchsbedingung hingegen könnte sie dann sehr langsam, vorsichtig und korrekt antworten.

  • Betrachtet man jetzt nur die Fehler bzw. %korrekt-Daten, dann sähe es nun so aus, als sei die schwierige Bedingung eigentlich leichter gewesen, denn die Vp hat dort ja weniger Fehler gemacht. Erst wenn man für beide Bedingungen auch die RT anschaut, sieht man, dass der Geschwindigkeitsunterschied etwas anderes impliziert.

Balanced Integration Score (BIS)

Um diesem Problem entgegenzutreten, sind in der Psychologie eine Reihe von Maßen vorgeschlagen worden, die RT und Fehler bzw. %korrekt irgendwie integrieren. Die Idee dahinter ist, dass in einem solchen Maß sich entgegengesetzte Tendenzen bei RT und %korrekt dann gegenseitig aufheben.

In einer Studie wurden mehrere solche Maße untersucht und verglichen. Zumindest für Aufgaben, wie wir sie durchführen, erwies sich dabei ein Maß als besonders adäquat: der Balanced Integration Score (BIS). Darüber hinaus zeigte das Paper, dass die anderen Scores ziemlich inadäquate Ergebnisse erzeugen können. Daher verwenden wir in unserer Arbeitsgruppe durchgehend den BIS.

Bei großem Interesse hier nachlesen: Liesefeld, H. R., & Janczyk, M. (2019). Combining speed and accuracy to control for speed-accuracy trade-offs(?). Behavior Research Methods, 51(1), 40–60. https://doi.org/10.3758/s13428-018-1076-x

9.2 Der Balanced Integration Score (BIS)

Im Folgenden berechnen wir den BIS für unsere Beispieldaten. Dazu müssen wir einen data.frame mit folgenden Infos erstellen:

  • die Anzahl korrekt beantworteter Trials
  • die Anzahl aller Trials
  • die mittleren RTs für korrekt beantwortete Trials
  • die mittleren RTs für alle Trials

Wir nennen den Datensatz “dc.m” (mit m = mean).

Der BIS verwendet %korrekt-Daten. Wie viel % der Trials korrekt waren, kann man nur für eine ganze Bedingung berechnen, nicht für einzelne Trials. Daher kann man den BIS nicht (sinnvoll) mit einem LMM auswerten (erinnere: LMM erfordert Trialdaten, nicht Bedingungsmittelwerte)!

dc.m <- dc %>% group_by( participant, posture, factor_A, factor_B ) %>%
  summarise(
    sdRtCorr = sd( rtClean[ respClean == 1 ] ),
    rtCorr = mean( rtClean[ respClean == 1 ] ),
    corrCount = sum( respClean == 1 ),
    totalCount = n(),
    pc = corrCount / totalCount *100
  )
`summarise()` has grouped output by 'participant', 'posture', 'factor_A'. You
can override using the `.groups` argument.

Der BIS berechnet nun z-standardisierte Werte für RT und %korrekt und subtrahiert dann die RT von %korrekt.

  • Durch die Standardisierung liegen sowohl RT als auch %korrekt als Werte mit Mittelwert 0 und s.d. 1 vor.

  • Wenn man sie nun subtrahiert, gehen also beide in gleichem Maße (mit vergleichbarer Größe) ein. Hohe %korrekt-Werte erhalten bei der Transformation hohe z-Werte. Hohe RTs ebenfalls.

Wenn also jemand einen Trade-off vornimmt und besonders sorgfältig (richtig) antwortet, indem er sehr langsam wird, dann wird von dem hohen %korrekt-Wert auch ein hoher RT-Wert abgezogen, so dass die Differenz entsprechend kleiner wird. Daher: je höher der BIS-Wert, desto besser war die Vp in der entsptrechenden Bedingung in der Zusammenschau von RT und %korrekt.

# BIS
dc.m <- dc.m %>% group_by( participant ) %>% mutate(
  zRt = ( rtCorr - mean( rtCorr ) ) / sqrt( sum ( ( rtCorr - mean( rtCorr ) ) ^ 2 ) / n() ),
  zPc = ( pc - mean( pc ) ) / sqrt( sum ( ( pc - mean( pc ) ) ^ 2 ) / n() ),
  bis = zPc - zRt
)
# group_by: jeder Teilnehmende wird separat standardisiert.

Die Autoren des BIS-Papers haben darauf hingewiesen, dass man sich gut überlegen muss, wie man standardisiert, denn Standardisierung eliminiert Unterschiede (dazu ist sie da).

Stellen Sie sich vor, Sie haben 2 Versuchsgruppen und standardisieren jede für sich; dann haben beide hinterher Mittelwerte um 0 und eventuelle Unterschiede zwischen den Gruppen sind rausgerechnet.

  • Bei einem Gruppenvergleich müsste man also beide Gruppen gemeinsam standardisieren; ist eine Gruppe schlechter als die andere, wird sie eher Werte <0 haben, die bessere Gruppe eher Werte >0.

  • Für within-subjects Experimente ist die Logik etwas anders: dort interessiert uns, wie sich eine einzelne Vp in der einen Bedingung im Vergleich zu einer anderen Bedingung verhält. Hierbei ist das Verhalten anderer Vpn nicht relevant. Wir standardisieren daher in solchen Experimenten jede Vp einzeln. Anders betrachtet: die Summe der BIS-Scores innerhalb jeder Person ist über die Bedingungen hinweg (bis auf Rundungsfehler) immer 0. [Im obigen Bsp. mit zwei Gruppen wären hingegen die Summen aller Werte über alle Vpn beider Gruppen 0 - nicht die Werte jeder Vp oder die Werte einer Gruppe].

Das kann man überprüfen:

dc.m %>% group_by( participant ) %>% 
  summarise(meanBIS=round(mean(bis)))
# A tibble: 18 × 2
   participant meanBIS
   <fct>         <dbl>
 1 B006b-08          0
 2 B006b-09          0
 3 B006b-10          0
 4 B006b-11          0
 5 B006b-12          0
 6 B006b-13          0
 7 B006b-14          0
 8 B006b-16          0
 9 B006b-17          0
10 B006b-18          0
11 B006b-19          0
12 B006b-20          0
13 B006b-21          0
14 B006b-22          0
15 B006b-24          0
16 B006b-25          0
17 B006b-26          0
18 B006b-27          0

9.3 Analyse des BIS

Da der BIS kontinuierliche Werte abbildet, jedoch nur 1 Wert pro Bedingung pro Vp berechnet werden kann (nicht ein BIS pro Trial), werten wir ihn statistisch mit der rm-Anova aus.

BIS.rmanova <- aov_ez(id = "participant", dv = "bis", data = dc.m, within = c("factor_A", "factor_B", "posture"))

BIS.rmanova
Anova Table (Type 3 tests)

Response: bis
                     Effect    df  MSE         F   ges p.value
1                  factor_A 1, 17 0.53      0.84  .004    .372
2                  factor_B 1, 17 1.09 56.98 ***  .352   <.001
3                   posture 1, 17 3.45 78.15 ***  .702   <.001
4         factor_A:factor_B 1, 17 0.56      0.12 <.001    .738
5          factor_A:posture 1, 17 0.30      0.01 <.001    .924
6          factor_B:posture 1, 17 0.49 86.16 ***  .271   <.001
7 factor_A:factor_B:posture 1, 17 0.31      1.75  .005    .204
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1

So ähnlich wie bei der rm-Anova für die RTs sehen wir auch hier Haupteffekte für factor_B, für posture und für die factor_B:posture Interaktion.

9.4 Visualisierung der Ergbenisse des Modells

Wieder können wir uns die EMM graphisch anschauen.

emm.bis.factorBXposture <- emmeans(BIS.rmanova, ~factor_B:posture)
ggplot(as.data.frame(emm.bis.factorBXposture), 
       aes(x=factor_B, y=emmean, color=posture)) + 
  geom_point(position = position_dodge(width=0.5), size=3) + 
  geom_errorbar(aes(ymin=lower.CL, ymax=upper.CL), position = position_dodge(width=0.5), width=0.2) + 
  ylab(label = "BIS score")

EMM zur für factor_B und posture

9.5 Post-hoc Vergleich zum BIS

Der paarweise Vergleich sieht wie folgt aus:

contrast(emm.bis.factorBXposture, method = "pairwise", adjust = "fdr")
 contrast                          estimate    SE df t.ratio p.value
 Level_1 uncr - Level_2 uncr          0.226 0.189 17   1.196  0.2479
 Level_1 uncr - Level_1 crossed       1.649 0.287 17   5.752  <.0001
 Level_1 uncr - Level_2 crossed       4.052 0.316 17  12.821  <.0001
 Level_2 uncr - Level_1 crossed       1.423 0.391 17   3.644  0.0024
 Level_2 uncr - Level_2 crossed       3.825 0.370 17  10.334  <.0001
 Level_1 crossed - Level_2 crossed    2.402 0.229 17  10.497  <.0001

Results are averaged over the levels of: factor_A 
P value adjustment: fdr method for 6 tests 

Wir hoffen gezeigt zu haben, dass selbst diese etwas komplexeren Auswertungsmethoden in R und der Interpretation nicht all zu schwer umzusetzen sind.

9.6 BIS als Funktion

Die oben angegebene Formel funktioniert, muss aber für jedes Skript angepasst werden. Stattdessen kann man auch diese Funktion in sein Skript einfügen und dann aufrufen:

###############################################################################
## compute Balanced Integration Score (BIS) using a grouping variable
## that is used for normalization
###############################################################################
bis_grouped <- function( dataFrame, rt, pc, groupingFactor ){
  # computes the BIS by normalizing per unit, rather than by the entire dataset.
  # We use this function to normalize by participant, given that we are interested
  # in within-subject factors.
  # rt, pc = variables to normalize
  # groupingFactor = grouping variable, e.g. participants, experimental groups
  # for equations, see
  # Liesefeld, H. R., & Janczyk, M. (2019). Combining speed and accuracy to control
  # for speed-accuracy trade-offs(?).
  # Behavior Research Methods, 51(1), 40–60.
  # https://doi.org/10.3758/s13428-018-1076-x
  dataFrame <- dataFrame %>% group_by( {{groupingFactor}} ) %>%
    mutate(
      varBisRtGrouped = sqrt( sum ( ( {{rt}} - mean( {{rt}} ) ) ^ 2 ) / n() ),
      varBisPcGrouped = sqrt( sum ( ( {{pc}} - mean( {{pc}} ) ) ^ 2 ) / n() ),
      n = n(),
      zRtGrouped = round( ( {{rt}} - mean( {{rt}} ) ) / varBisRtGrouped, 3 ),
      zPcGrouped = round( ( {{pc}} - mean( {{pc}} ) ) / varBisPcGrouped, 3 ),
      bisGrouped = zPcGrouped - zRtGrouped
    )
  return( dataFrame )
}

# Aufruf:
dc.m <- bis_grouped( dc.m, rtCorr, pc, participant )