Datensatz

Für diese Übung brauchen Sie den Datensatz “data_kappa.csv”. Dieser beinhaltet die Daten von drei physiotherapeutischen Tests:

  • Bei der ersten Testung haben zwei unabhängige Rater die Beweglichkeit der Lendenwirbelsäule beurteilt (1 = nicht eingeschränkt, 2 = leicht eingeschränkt, 3 = moderat eingeschränkt, 4 = stark eingeschränkt).
  • Bei der zweiten Testung haben drei unabhängige Rater einen Test des Hüftgelenks (FADDIR) durchgeführt (1 = negativ, 2 = positiv).
  • Bei der dritten Testung haben zwei unabhängige Rater die Beweglichkeit des Sprunggelenks beurteilt (1 = normal, 2 = eingeschränkt).

Übung 1

Aufgaben

  1. Importieren Sie den Datensatz in R. Wandeln Sie die Variablen in Faktoren um.
  2. Stellen Sie die absoluten und relativen Häufigkeiten der Übereinstimmung bei der Beurteilung des Rückens in einer Kreuztabelle dar. Was fällt auf? Tipp: ctable() aus dem Paket summarytools
  3. Wie hoch ist das prozentuale Agreement?
  4. Berechnen sie den ungewichteten Kappa-Koeffizienten und dessen 95% Konfidenzintervall. Interpretieren Sie die Werte. Tipp: cohen.kappa() aus dem Paket psych.
  5. Ist die Berechnung eines gewichteteten Kappa-Koeffizienten in diesem Fall sinnvoll? Begründen Sie. Erklären Sie allfällige Abweichungen zum nicht gewichteten Koeffizienten.

Lösung

Datenimport und Data-Cleaning:

library(rio)
df.kappa <- import("../../data/data-kappa.csv")

library(tidyverse)
df.kappa <- df.kappa %>% 
  mutate_all(as.factor) 
# Man könnte es auch für jede Variable indivuduell tun mit: 
# df.kappa$rater1_back <- factor(df.kappa$rater1_back)

Tabellarsiche Darstellung der Daten:

library(summarytools)
ctable(df.kappa$rater1_back, df.kappa$rater2_back, prop = "t")
## Cross-Tabulation, Total Proportions  
## rater1_back * rater2_back  
## Data Frame: df.kappa  
## 
## ------------- ------------- ------------ ------------ ------------ ----------- -------------
##                 rater2_back            1            2            3           4         Total
##   rater1_back                                                                               
##             1                  2 ( 3.3%)    3 ( 5.0%)    3 ( 5.0%)   0 ( 0.0%)    8 ( 13.3%)
##             2                  2 ( 3.3%)   13 (21.7%)    4 ( 6.7%)   1 ( 1.7%)   20 ( 33.3%)
##             3                  5 ( 8.3%)    2 ( 3.3%)    7 (11.7%)   2 ( 3.3%)   16 ( 26.7%)
##             4                  3 ( 5.0%)    8 (13.3%)    1 ( 1.7%)   4 ( 6.7%)   16 ( 26.7%)
##         Total                 12 (20.0%)   26 (43.3%)   15 (25.0%)   7 (11.7%)   60 (100.0%)
## ------------- ------------- ------------ ------------ ------------ ----------- -------------

Die Ausprägung 1 kommt am wenigsten vor, die Ausprägung 2 am häufigsten. Insgesamt ist die Verteilung aber relativ gleichmässig.



Es gibt verschiedene Möglichkeiten, um das prozentuale Agreement zu bestimmen. Am einfachsten geht es mit der agree() Funktion aus dem irr Package. Man könnte natürlich auch einfach die Werte in der Diagonale der oben dargestellten Kreuztabelle addieren.

library(irr)
agree(df.kappa[, c("rater1_back", "rater2_back")])
##  Percentage agreement (Tolerance=0)
## 
##  Subjects = 60 
##    Raters = 2 
##   %-agree = 43.3


library(psych)
cohen.kappa(table(df.kappa$rater1_back, df.kappa$rater2_back))
## Call: cohen.kappa1(x = x, w = w, n.obs = n.obs, alpha = alpha, levels = levels, 
##     w.exp = w.exp)
## 
## Cohen Kappa and Weighted Kappa correlation coefficients and confidence boundaries 
##                   lower estimate upper
## unweighted kappa  0.065    0.225  0.38
## weighted kappa   -0.138    0.094  0.33
## 
##  Number of subjects = 60

Der ungewichtete Kappa-Koeffizient beträgt 0.225, was einer “fairen” Reliabilität entspricht. Weil das 95% CI die Nullhypothese (K = 0) nicht schneidet, ist die beobachtete Übereinstimmung signifikant höher als die zufällig erwartete Übereinstimmung. Wenn man ganz streng ist, nimmt man für die Interpretation die untere Schranke des 95% CIs. In diesem Fall liegt eine schlechte Reliabiliät vor.



library(psych)
cohen.kappa(table(df.kappa$rater1_back, df.kappa$rater2_back))
## Call: cohen.kappa1(x = x, w = w, n.obs = n.obs, alpha = alpha, levels = levels, 
##     w.exp = w.exp)
## 
## Cohen Kappa and Weighted Kappa correlation coefficients and confidence boundaries 
##                   lower estimate upper
## unweighted kappa  0.065    0.225  0.38
## weighted kappa   -0.138    0.094  0.33
## 
##  Number of subjects = 60

Die Daten sind eindeutig ordinal skaliert, ein gewichteter Kappa-Koeffizient macht daher Sinn (und solle dem nicht-gewichteten vorgezogen werden). Der Output der Funktion cohen.kappa() gibt uns bereits einen gewichteten Kappa-Koeffizienten. Standardmässig wird eine quadrierte Gewichtung gewählt. Der Koeffizeint ist deutlich tiefer, wir haben so gut wie keine Reliabiliät, Das 95% CI schneidet die 0 deutlich. In 5% der Fälle kommt es vor, dass Rater1 eine 4, und Rater2 eine 1 bewertet. In 13.3% der Fälle kommt es vor, dass ein Rater eine 1 und der andere eine 3 bewertet. Diese Abweichungen drücken den gewichteten Koeffizienten nach unten.

Exkurs

Falls man anders gewichten möchte, können die Gewichte in ein einer Matrix hinterlegt werden.

weights <- matrix(c(0,1,2,4,
                    1,0,1,2,
                    2,1,0,1,
                    4,2,1,0), byrow = TRUE, ncol = 4)
cohen.kappa(table(df.kappa$rater1_back, df.kappa$rater2_back), w = weights)
## Call: cohen.kappa1(x = x, w = w, n.obs = n.obs, alpha = alpha, levels = levels, 
##     w.exp = w.exp)
## 
## Cohen Kappa and Weighted Kappa correlation coefficients and confidence boundaries 
##                   lower estimate upper
## unweighted kappa  0.065     0.22  0.38
## weighted kappa   -1.000     0.15  1.00
## 
##  Number of subjects = 60

Achtung: Wenn man die Gewichte manuell festlegt, vergrössert sich der Standardfehler deutlich. Offizielle Empfehlung im Help-Menü des psych Packages: “In the case of confidence intervals being artificially truncated to +/- 1, it is helpful to compare the results of a boot strap resample”.



Übung 2

Aufgabe

  1. Berechnen und interpretieren Sie einen geeigneten Reliabilitätskoeffizienten für die Ratings der drei Rater beim Hüft-Test “FADDIR”.

Lösung

In dieser Situation sollte der Kappa-Koeffizient nach Fliess berechnet werden.

library(DescTools)
KappaM(df.kappa[,c("rater1_hip", "rater2_hip", "rater3_hip")], method = "Fleiss", conf.level = 0.95)
##     kappa    lwr.ci    upr.ci 
## 0.5238522 0.3765323 0.6711721

Es liegt moderate bis gute Reliabiliät vor: je nach dem, ob man den Koeffizienten selber (eher grosszügig) oder die untere Schranke des CIs für die Interpretation braucht. Weil das CI den Nullwert deutlich nicht einschliesst, ist die Übereinstimmung stat. signifikant besser, als die zufällig erwartete Übereinstimmung. Im Kontext eines manuellen, klinischen Tests ist eine Reliabilität in dieser Grössenordnung zufriedenstellend.

Die Funktion kappam.fleiss() funktioniert ebenfalls und liefert Details zu den einzelnen Ausprägungen (dafür kein 95% CI):

irr::kappam.fleiss(df.kappa[,3:5], detail = TRUE)
##  Fleiss' Kappa for m Raters
## 
##  Subjects = 59 
##    Raters = 3 
##     Kappa = 0.524 
## 
##         z = 6.97 
##   p-value = 3.18e-12 
## 
##   Kappa     z p.value
## 1 0.524 6.969   0.000
## 2 0.524 6.969   0.000


Übung 3

Aufgaben

  1. Sie wollen die Reliabilität für die Beurteilung der Beweglichkeit des Sprunggelenks evaluieren. Welcher Koeffizient sollte hier berechnet werden? Begründen Sie die Antwort.
  2. Berechnen Sie den geeigneten Reliabilitäts-Koeffizienten und interpretieren Sie.

Lösungen

library(summarytools)
ctable(df.kappa$rater1_foot, df.kappa$rater2_foot, prop = "t", useNA = "no")
## Cross-Tabulation, Total Proportions  
## rater1_foot * rater2_foot  
## Data Frame: df.kappa  
## 
## ------------- ------------- ------------ ------------ -------------
##                 rater2_foot            1            2         Total
##   rater1_foot                                                      
##             1                  6 (10.2%)    5 ( 8.5%)   11 ( 18.6%)
##             2                 10 (16.9%)   38 (64.4%)   48 ( 81.4%)
##         Total                 16 (27.1%)   43 (72.9%)   59 (100.0%)
## ------------- ------------- ------------ ------------ -------------

Man sieht, dass die Ausprägung 1 (normal) deutlich weniger häufig vorkommt, als die Ausprägung 2 (eingeschränkt). Es handelt sich demnach um eine schiefe Verteilung. Bei schiefen Verteilungen unterschätzt der Kappa-Koeffizient die Reliabiliät häufig. Daher sollte man als Alternative Gwet’s AC1 Statistik oder das PABAK berechnen. Das PABAK ist zu bevorzugen, da es am robustesten ist.



Zuerst der normale Kappa-Koeffizient:

library(psych)
cohen.kappa(df.kappa[,c("rater1_foot", "rater2_foot")])
## Call: cohen.kappa1(x = x, w = w, n.obs = n.obs, alpha = alpha, levels = levels, 
##     w.exp = w.exp)
## 
## Cohen Kappa and Weighted Kappa correlation coefficients and confidence boundaries 
##                  lower estimate upper
## unweighted kappa 0.013     0.29  0.56
## weighted kappa   0.013     0.29  0.56
## 
##  Number of subjects = 59


Nun das Prevalänz und Verzerrungadjustierte Kappa (PABAK):

library(epiR)
epi.kappa(table(df.kappa$rater1_foot, df.kappa$rater2_foot), method = "fleiss")$pabak
##         est     lower     upper
## 1 0.4915254 0.2311519 0.7003584

Dieser ist, wie aufgrund der schiefen Verteilung angenommen, deutlich höher.


Eine weitere Alternative ist Gwet’s AC1 Statistik:

library(irrCAC)
gwet.ac1.raw(na.omit(df.kappa[, c("rater1_foot", "rater2_foot")]), conflev = 0.95)$est
##   coeff.name        pa        pe coeff.val coeff.se      conf.int      p.value
## 1        AC1 0.7457627 0.3529158    0.6071  0.10522 (0.396,0.818) 3.255535e-07
##       w.name
## 1 unweighted

Dieser Koeffizient ist sogar noch etwas höher. Laut dem Paper von Xu et al. (2014) überschätzt er die Reliabilität bei ganz hohen, bzw. ganz tiefen Prävalenzen. Tatsächlich ist er relativ nah am prozentualen Agreement (74.6%) In dieser Situation ist wohl das PABAK zu bevorzugen.



Zusammenfassung

  • Zur Bestimmung der Reliabilität bei nominalen Variablen wird meistens der Kappa-Koeffizient berechnet.
  • Ein Kappa-Koeffizient beschreibt die Übereinstimmung von Ratern, unter der Berücksichtigung der durch Zufall zu erwartenden Übereinstimmung.
  • Bei ordinalen Variablen wird meistens ein gewichteter Kappa-Koeffizient berechnet. Eine quadratische Gewichtung ist am gängigsten und die Defaulteinstellung bei den meisten Packages.
  • Bei mehr als zwei Ratern wird der Kappa-Koeffizient nach Fleiss berechnet.
  • Bei sehr tiefen oder sehr hohen Prävalenzen fällt der Kappa-Koeffizient oft sehr tief aus. Mögliche Alternativen sind das PABAK oder Gwet’s AC1 Statistik.
  • Zur Interpretation der Reliabilitätskoeffizienten existieren verschiedene Cut-offs. Streng genommen müsste man für die Interpretation die untere Schranke des 95% CIs nehmen. Die Berücksichtigung des jeweiligen Kontexts ist bei der Interpretation wichtig.