Kapitel 35 Berechnungen Standard-Messfehler (SEM)

35.1 SEM aus ICC

Nachdem wir nun den ICC kennengelernt haben, betrachten wir in diesem Kapitel drei Berechnungen für den Standardmessfehlers, auch Standard Error of Measurement oder SEM genannt.

Am Ende des Kapitels wissen wir folgendes:

  • Der SEM kann aus dem ICC berechnet werden, wenn es keinen systematischen Fehler gibt.
  • Der ICC ist abhängig vom SEM und von der Streuung des zu messenden Merkmals in der Stichprobe - Bei gleichem SEM wird der ICC höher (besser) sein, wenn die Standardabweichung des Merkmals grösser ist. Der SEM hingegen ist nicht von der Variabilität zwischen den Personen betroffen.

35.2 Beispiel schmerzhafte und gesunde Schulter

# load packages ####
library(psych)
library(tidyverse)
library(janitor)
library(BlandAltmanLeh)

35.3 Simulieren der Daten

Wir simulieren wieder Daten für die schmerzhaften und die gesunden Schultern

set.seed(12293425)
sampleSize=100
painful_shoulder<-rnorm(sampleSize, 90, 20)

healthy_shoulder<-rnorm(sampleSize, 180, 2)
id<-1:sampleSize

data_shoulder<-data.frame(id, painful_shoulder, healthy_shoulder)

35.4 Streuung der Beweglichkeit

Die nächsten beiden Graphiken zeigen die Variabilität der Beweglichkeiten in den schmerzhaften und den gesunden Schultern.

par(mfrow = c(1, 2))
plot(painful_shoulder, id, xlim=c(0,190))

plot(healthy_shoulder, id, xlim=c(0,190))
Variabilität in den schmerzhaften (links) und gesunden (rechts) Schultern. Auf der horizontalen (x) Achse sehen wir die Flexion in Graden. Auf der vertikalen (y) Achse sehen wir die ID-Nummern, d.h. jede Patientin und jeder Patient ist auf einer Linie.

Abbildung 3.1: Variabilität in den schmerzhaften (links) und gesunden (rechts) Schultern. Auf der horizontalen (x) Achse sehen wir die Flexion in Graden. Auf der vertikalen (y) Achse sehen wir die ID-Nummern, d.h. jede Patientin und jeder Patient ist auf einer Linie.

par(mfrow = c(1, 1))
sd(healthy_shoulder)
## [1] 1.956707
sd(painful_shoulder)
## [1] 20.61599

35.5 Simulieren der Test-Retest Fehler

data_shoulder<-data_shoulder %>% 
  mutate(painful_shoulder_1=painful_shoulder+rnorm(nrow(.), 0, 5)) %>% 
  mutate(healthy_shoulder_1=healthy_shoulder+rnorm(nrow(.), 0, 5)) %>% 
  mutate(painful_shoulder_2=painful_shoulder+rnorm(nrow(.), 0, 5)) %>% 
  mutate(healthy_shoulder_2=healthy_shoulder+rnorm(nrow(.), 0, 5))

35.6 Berechnen des Standardmessfehlers (Standard Error of the Mean, SEM)

Wir können den SEM mit drei unterschiedlichen Formeln berechnen.

Ein Problem ist der systematische Fehler: Wenn wir systematischen Fehler haben (d.h. einen Unterschied in den Mittelwerten der Messung 1 und Messung 2), dürfen wir nicht alle Formeln benutzen - wir werden das jeweils bei den Formeln angeben.

35.6.1 Variante 1: \(\frac{SD~Difference~}{\sqrt{2}}\)

(Achtung: diese Formel berücksichtigt den systematischen Fehler nicht!)

SEM_painful_shoulder =(sd(data_shoulder$painful_shoulder_2-data_shoulder$painful_shoulder_1))/2^0.5
SEM_painful_shoulder
## [1] 4.350445
SEM_healthy_shoulder=(sd(data_shoulder$healthy_shoulder_2-data_shoulder$healthy_shoulder_1))/2^0.5
SEM_healthy_shoulder
## [1] 4.618261
SEM_variante_1<-SEM_healthy_shoulder

35.6.2 Variante 2: \(\sigma\)Merkmal\(\sqrt{(1-ICC)}\) = SDpooled\(\sqrt{(1-ICC)}\)

(Achtung: auch diese Formel berücksichtigt den systematischen Fehler nicht!) Für diese Variante müssen wir zuerst den ICC berechnen. Da diese Formel den systematischen Fehler nicht berücksichtigt, dürfen wir sie nur benutzen, wenn es keinen systematischen Fehler gibt, oder wenn wir ihn nicht berücksichtigen wollen.

Wir benutzen dazu die gepoolte Standardabweichung der beiden Messungen. Die Formel ist unten im R-Chunk. Diese Webseite gibt noch mehr Informationen zu der gepoolten Standardabweichung

out<-psych::ICC(data_shoulder[c("healthy_shoulder_1", "healthy_shoulder_2")])
## boundary (singular) fit: see help('isSingular')
pooled_sd<-sqrt((sd(data_shoulder$healthy_shoulder_1, na.rm=TRUE)^2 +sd(data_shoulder$healthy_shoulder_2, na.rm=TRUE)^2)/2)

ICC2_1<-out$results$ICC[3]

Der ICC2,1 für die Gesunde Seite ist 0.26

Jetzt können wir die Formel anwenden:

SEM_variante_2<-pooled_sd*sqrt(1-ICC2_1)
SEM_variante_2
## [1] 4.609313

35.6.3 Variante 3: SEM = \(\sqrt{sigma^2~Error~}\)

Nun ist es nicht ganz so einfach, diese Fehler-Varianz (\(\sigma^2~Error~\)) zu erhalten. Wir können sie aus dem Objekt extrahieren, das wir mit dem ICC Befehls des psych Pakets erhalten

Dies sehen wir im nächsten R-Abschnitt:

Den nächsten Code-Abschnitt braucht ihr als Bachelor of Science nicht zu verstehen - Wir brauchen diesen Code um die benötigten Varianzkomponenten zu erhalten. Diese benötigen wir, um den SEM für das Agreement zu berechnen. Wer mehr dazu wissen möchte, sollte den folgenden Artikel lesen: Vet, H. C., Terwee, C. B., Knol, D. L., & Bouter, L. M. (2006). When to use agreement versus reliability measures. Journal of clinical epidemiology, 59(10), 1033-1039

out
## Call: psych::ICC(x = data_shoulder[c("healthy_shoulder_1", "healthy_shoulder_2")])
## 
## Intraclass correlation coefficients 
##                          type  ICC   F df1 df2      p lower bound upper bound
## Single_raters_absolute   ICC1 0.26 1.7  99 100 0.0045       0.066        0.43
## Single_random_raters     ICC2 0.26 1.7  99  99 0.0046       0.066        0.43
## Single_fixed_raters      ICC3 0.26 1.7  99  99 0.0046       0.065        0.43
## Average_raters_absolute ICC1k 0.41 1.7  99 100 0.0045       0.124        0.60
## Average_random_raters   ICC2k 0.41 1.7  99  99 0.0046       0.123        0.60
## Average_fixed_raters    ICC3k 0.41 1.7  99  99 0.0046       0.123        0.60
## 
##  Number of subjects = 100     Number of Judges =  2
## See the help file for a discussion of the other 4 McGraw and Wong estimates,
out$stats
##           subjects     Judges   Residual
## df    9.900000e+01  1.0000000   99.00000
## SumSq 3.555151e+03 21.1970149 2098.50445
## MS    3.591061e+01 21.1970149   21.19701
## F     1.694135e+00  1.0000000         NA
## p     4.645463e-03  0.3197485         NA
out$MSW
## [1] 21.19701
numberOfPatients=nrow(data_shoulder)
numberOfRaters=2

varBetweenPatients<-out$stats[3,1]
varResidual<-out$stats[3,3]
varTrueBetweenPatients<-(varBetweenPatients-varResidual)/numberOfRaters
varBetweenRaters<-out$stats[3,2]
varTrueBetweenRaters<-(varBetweenRaters-varResidual)/numberOfPatients

ICC_agreement<-varTrueBetweenPatients/(varTrueBetweenPatients+varTrueBetweenRaters+varResidual)
ICC_agreement
## [1] 0.2576468
# In a lot of publications, you see these formulae from Shrout and Fleiss
# ICC_3.1<-(varBetweenPatients-varResidual)/varBetweenPatients
# ICC_3.1
ICC_2.1 <-(varBetweenPatients-varResidual) / (varBetweenPatients+(numberOfRaters-1)*varResidual+((numberOfRaters*(varBetweenRaters-varResidual))/numberOfPatients))
ICC_2.1
## [1] 0.2576468
# Method 1, see page 111 in Measurement in Medicine 
# For SEMagreement 
varError<-varTrueBetweenRaters+varResidual
SEMagreement<-sqrt(varError)
print(SEMagreement)
## [1] 4.604022
SEM_variante_3<-SEMagreement

SEM Agreement für die gesunde Seite: Der ICC2,1 für die gesunde Seite ist 0.26 mit einem 95% Konfidenzintervall von 0.07 bis 0.43. DER SEMagreement der gesunden Schultern, berechnet mit der Formel aus dem Artikel von de Vet und Kolleginnen, ist: 4.6.

Wir können die drei Varianten noch einmal hier darstellen:

Variante 1: 4.6
Variante 2: 4.6
Variante 3: 4.6

35.7 Smallest Detectable Change

(Auch Minimal Detectable Change oder Difference genannt.) Wir werden in einem späteren Kapitel noch näher auf den Smallest Detectable Change eingehen, hier nur eine kurze Aussage:

  • Der Smallest Detectable Change auf dem 95% Niveau (SDC95%) wird mit 1.96*\(\sqrt{2}\) = 2.77 Mal SEM berechnet.
  • Die Hälfte des Intervalls zwischen den Limits of Agreement entspricht dem Smallest Detectable Change auf dem 95% Niveau (SDC95%)

Wir können das mit dem Bland-Altman Plot anschauen

library(MethComp)
library(BlandAltmanLeh)
mean(data_shoulder$painful_shoulder_1)
## [1] 92.09715
mean(data_shoulder$painful_shoulder_2)
## [1] 91.96726
bp1<-bland.altman.plot(data_shoulder$painful_shoulder_1, data_shoulder$painful_shoulder_2, xlim=c(0,200), graph.sys = "ggplot2")
bp1<-bp1+xlim(0,200)+ylim(-20,20)+theme_classic()+labs(x="Mean of variables: painful_shoulder_1, painful_shoulder_2", y="Difference painful_shoulder_1 - painful_shoulder_2")
bp1

bp2<-bland.altman.plot(data_shoulder$healthy_shoulder_1, data_shoulder$healthy_shoulder_2,  graph.sys="ggplot2")
bp2<-bp2+xlim(0,200)+ylim(-20,20)+theme_classic()+labs(x="Mean of variables: healthy_shoulder_1, healthy_shoulder_2", y="Difference healthy_shoulder_1 - healthy_shoulder_2")
bp2
Bland Altman Plot. Auf der vertikalen Achse sehen wir die Differenz der Messung 1 minus die Messung 2 der schmerzhaften Schultern; auf der horizontalen Achse sehen wir den Durchschnitt der beiden Messungen. Wir sehen, dass es praktischen keinen systematische Differenz (Fehler) zwischen den beiden Messungen gibt, d.h. der Mittelwert der Differenz (mittlere gestrichelte Linie) ist praktisch bei Null.Bland Altman Plot. Auf der vertikalen Achse sehen wir die Differenz der Messung 1 minus die Messung 2 der schmerzhaften Schultern; auf der horizontalen Achse sehen wir den Durchschnitt der beiden Messungen. Wir sehen, dass es praktischen keinen systematische Differenz (Fehler) zwischen den beiden Messungen gibt, d.h. der Mittelwert der Differenz (mittlere gestrichelte Linie) ist praktisch bei Null.

Abbildung 22.1: Bland Altman Plot. Auf der vertikalen Achse sehen wir die Differenz der Messung 1 minus die Messung 2 der schmerzhaften Schultern; auf der horizontalen Achse sehen wir den Durchschnitt der beiden Messungen. Wir sehen, dass es praktischen keinen systematische Differenz (Fehler) zwischen den beiden Messungen gibt, d.h. der Mittelwert der Differenz (mittlere gestrichelte Linie) ist praktisch bei Null.

Wir könnten sogar noch visuell untersuchen, ob die Differenz zwischen den beiden Messungen über die Werte der Messungen gleich bleibt. Wir sehen, dass es einen leichten Trend gibt, die Daten sind jedoch immer noch kompatibel mit der Hypothese, dass die Differenz über alle Wertebereiche 0 ist.

bp1+geom_smooth(method=lm)
## `geom_smooth()` using formula = 'y ~ x'
Bland-Altman Plot mit eingezeichneter Regressionslinie für die Differenzen über die Durchschnittswerte. Wir sehen einen leichten Trend dafür, dass die Differenzen sich verändern über die Durchschnittswerte. Angesichts des Konfidenzintervalles (graues Band um die blaue Regressionslinie) können wir jedoch die Nullhypothese (dass die Differenz über alle Wertebereiche 0 ist) beibehalten.

Abbildung 1.2: Bland-Altman Plot mit eingezeichneter Regressionslinie für die Differenzen über die Durchschnittswerte. Wir sehen einen leichten Trend dafür, dass die Differenzen sich verändern über die Durchschnittswerte. Angesichts des Konfidenzintervalles (graues Band um die blaue Regressionslinie) können wir jedoch die Nullhypothese (dass die Differenz über alle Wertebereiche 0 ist) beibehalten.

res<-bland.altman.stats(data_shoulder$healthy_shoulder_1, data_shoulder$healthy_shoulder_2)
res$upper.limit
## [1] 13.20601
res$lower.limit
## [1] -12.39633

Dort hatten wir die obere Limit of Agreement bei 13.2 und die untere Limit of Agreement bei -12.4. Die Hälfte des Intervalls ist somit 12.8. Mit der 2.77 Mal SEM Formel kommen wir auf einen SDC95% von 12.8. Wir sehen also, dass der SEM eine Hälfte der Distanz zwischen den Limits of Agreements ist.

35.8 Wir berechnen nun das Gleiche noch für die schmerzhafte Seite:

35.8.1 Variante 1: \(\frac{SD~Difference~}{\sqrt{2}}\) (Achtung: diese Formel berücksichtigt den systematischen Fehler nicht!)

SEM_painful_shoulder =(sd(data_shoulder$painful_shoulder_2-data_shoulder$painful_shoulder_1))/2^0.5
SEM_variante_1<-SEM_painful_shoulder

35.8.2 Variante 2: SDMessung\(\sqrt{(1-ICC)}\)

(Achtung: auch diese Formel berücksichtigt den systematischen Fehler nicht!) Für diese Variante müssen wir zuerst den ICC berechnen. Da diese Formel den systematischen Fehler nicht berücksichtigt, dürfen wir sie nur benutzen, wenn es keinen systematischen Fehler gibt, oder wenn wir ihn nicht berücksichtigen wollen.

Wir benutzen dazu die gepoolte Standardabweichung der beiden Messungen. Die Formel ist unten im R-Chunk. Diese Webseite gibt noch mehr Informationen zu der gepoolten Standardabweichung

out<-psych::ICC(data_shoulder[c("painful_shoulder_1", "painful_shoulder_2")])
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
## Model failed to converge with max|grad| = 0.0178828 (tol = 0.002, component 1)
pooled_sd<-sqrt((sd(data_shoulder$painful_shoulder_1, na.rm=TRUE)^2 +sd(data_shoulder$painful_shoulder_1, na.rm=TRUE)^2)/2)
ICC2_1<-out$results$ICC[3]

Der ICC2,1 für die schmerzhafte Seite ist 0.96

Jetzt können wir die Formel anwenden:

SEM_variante_2<-pooled_sd*sqrt(1-ICC2_1)
SEM_variante_2
## [1] 4.280763

35.8.3 Variante 3: SEM = \(\sqrt{sigma^2~Error~}\)

Nun ist es nicht ganz so einfach, diese Fehler-Varianz (\(\sigma^2~Error~\)) zu erhalten. Wir können sie aus dem Objekt extrahieren, das wir mit dem ICC Befehls des psych Pakets erhalten

Dies sehen wir im nächsten R-Abschnitt:

Den nächsten Code-Abschnitt braucht ihr als Bachelor of Science nicht zu verstehen - Wir brauchen diesen Code um die benötigten Varianzkomponenten zu erhalten. Diese benötigen wir, um den SEM für das Agreement zu berechnen. Wer mehr dazu wissen möchte, sollte den folgenden Artikel lesen: Vet, H. C., Terwee, C. B., Knol, D. L., & Bouter, L. M. (2006). When to use agreement versus reliability measures. Journal of clinical epidemiology, 59(10), 1033-1039

# out
# out$stats
# out$MSW
numberOfPatients=nrow(data_shoulder)
numberOfRaters=2

varBetweenPatients<-out$stats[3,1]
varResidual<-out$stats[3,3]
varTrueBetweenPatients<-(varBetweenPatients-varResidual)/numberOfRaters
varBetweenRaters<-out$stats[3,2]
varTrueBetweenRaters<-(varBetweenRaters-varResidual)/numberOfPatients

ICC_agreement<-varTrueBetweenPatients/(varTrueBetweenPatients+varTrueBetweenRaters+varResidual)
# In a lot of publications, you see these formula from Shrout and Fleiss
# ICC_3.1<-(varBetweenPatients-varResidual)/varBetweenPatients
# ICC_3.1
ICC_2.1 <-(varBetweenPatients-varResidual) / (varBetweenPatients+(numberOfRaters-1)*varResidual+((numberOfRaters*(varBetweenRaters-varResidual))/numberOfPatients))
# Method 1, see page 111 in Measurement in Medicine 
# For SEMagreement 
varError<-varTrueBetweenRaters+varResidual
SEMagreement<-sqrt(varError)
SEM_variante_3<-SEMagreement

SEM Agreement für die schmerzhafte Seite: Der ICC2,1 für die schmerzhafte Seite ist 0.96 mit einem 95% Konfidenzintervall von 0.94 bis 0.97. Wir sehen, dass der ICC für die schmerzhafte Seite, bei vergleichbarem SEM, deutlich besser ist als der ICC für die gesunde Seite. DER SEMagreement der gesunden Schultern, berechnet mit der Formel aus dem Artikel von de Vet und Kolleginnen, ist: 4.33.

Wir können die drei Varianten noch einmal hier darstellen:

Variante 1: 4.4
Variante 2: 4.3
Variante 3: 4.3

35.9 Smallest Detectable Change für die schmerzhafte Seite

Mit der 2.77 Mal SEM Formel kommen wir auf einen SDC95% von 12.001.

  • Wir sehen, dass der SDC für die gesunde und die schmerzhafte Seite praktisch gleich ist, obschon der ICC anders ist. Warum? Der SDC wird mit dem SEM berechnet.

Hier noch eine wichtige Bemerkung: Wir dürfen den Smallest Detectable Change / Smallest Detectable Difference / Minimal Detectable Change nicht mit dem Minimal Clinically Important Change / Difference verwechseln. Siehe diesen Artikel (hier klicken) dazu[target=“_blank”].

Je genauer - d.h. reliabler - wir messen können, desto kleinere Veränderungen können wir zuverlässig erkennen. Ist der Smallest Detectable Change grösser als eine Veränderung des Patienten, sind wir nicht sicher, ob es eine echte Veränderung ist, oder nur ein Messfehler.