Der Datensatz “hospAB.csv” für diese Übung enthält die folgenden Variablen:
Ziel ist es herauszufinden, ob sich die Odds, um zu sterben, zwischen den beiden Spitälern unterscheiden.
Datensatz importieren:
library(rio)
<- import("~/Documents/Git/fm-msc-bfh/Exercises/Confounding/hospAB.csv") d.hospital
Es bietet sich an, bei allen qualitativen Variablen Faktoren zu erstellen:
str(d.hospital)
## 'data.frame': 1600 obs. of 5 variables:
## $ risk : int 1 2 1 2 1 2 1 2 1 2 ...
## $ sex : int 2 2 2 2 1 1 1 1 2 2 ...
## $ age : int 0 0 1 1 0 0 1 1 0 0 ...
## $ death : int 1 1 1 1 1 1 1 1 1 1 ...
## $ hospital: int 0 0 0 0 0 0 0 0 1 1 ...
$risk <- factor(d.hospital$risk, levels = c(1,2),
d.hospitallabels = c("low risk", "high risk"))
$sex <- factor(d.hospital$sex, levels = c(1,2),
d.hospitallabels = c("female", "male"))
$age <- factor(d.hospital$age, levels = c(0,1),
d.hospitallabels = c("<60", "60+"))
$death <- factor(d.hospital$death, levels = c(0,1),
d.hospitallabels = c("survived", "died"))
$hospital <- factor(d.hospital$hospital, levels = c(0,1),
d.hospitallabels = c("A", "B"))
str(d.hospital)
## 'data.frame': 1600 obs. of 5 variables:
## $ risk : Factor w/ 2 levels "low risk","high risk": 1 2 1 2 1 2 1 2 1 2 ...
## $ sex : Factor w/ 2 levels "female","male": 2 2 2 2 1 1 1 1 2 2 ...
## $ age : Factor w/ 2 levels "<60","60+": 1 1 2 2 1 1 2 2 1 1 ...
## $ death : Factor w/ 2 levels "survived","died": 2 2 2 2 2 2 2 2 2 2 ...
## $ hospital: Factor w/ 2 levels "A","B": 1 1 1 1 1 1 1 1 2 2 ...
Da es sich um rein qualitative Daten handelt, eigenen sich Balkendiagramme, um deren Verteilung zu betrachten:
barplot(table(d.hospital$risk, d.hospital$hospital),
legend = TRUE, main = "Risk", xlab = "Hospital")
barplot(table(d.hospital$sex, d.hospital$hospital),
legend = TRUE, main = "Sex", xlab = "Hospital")
barplot(table(d.hospital$age, d.hospital$hospital),
legend = TRUE, main = "Age", xlab = "Hospital")
barplot(table(d.hospital$death, d.hospital$hospital),
legend = TRUE, main = "Death", xlab = "Hospital")
Für die tidyverse-Fans hier noch eine etwas elegantere Lösung…
library(tidyverse)
%>%
d.hospital pivot_longer(risk:death, names_to = "profile", values_to = "values") %>%
ggplot(aes(x = values, fill = hospital)) + geom_bar()
Man sieht, dass die Risikofaktoren (high risk
,
male
, 60+
) in Spital B häufiger vorkommen.
prop.test()
oddsratio()
aus dem Paket
epitools
Zuerst wird die 2x2 Tabelle erstellt:
<- table(d.hospital$hospital, d.hospital$death)
tab tab
##
## survived died
## A 760 40
## B 719 81
Darin ist ersichtlich, dass es in Spital B mehr Todesfälle gibt.
Wir brauchen den prop.test()
, um die Proportion an
Todesfällen der beiden Spitäler statistisch zu vergleichen.
prop.test(c(40,81), c(800, 800))
##
## 2-sample test for equality of proportions with continuity correction
##
## data: c(40, 81) out of c(800, 800)
## X-squared = 14.305, df = 1, p-value = 0.0001555
## alternative hypothesis: two.sided
## 95 percent confidence interval:
## -0.07828847 -0.02421153
## sample estimates:
## prop 1 prop 2
## 0.05000 0.10125
# Der erste Vektor steht für die "Events", der zweite für das n pro Gruppe
Die Proportionsdifferenz beträgt 0.10125- 0.05000 = 5.125%. Das 95% CI schneidet die H0 nicht. Der p-Wert ist mit 0.01% klein. Es scheint also Evidenz dafür zu geben, dass in Spital B wirklich mehr Menschen sterben…
Mit der Berechnung des OR kommen wir zum gleichen Fazit:
library(epitools)
oddsratio(tab, correction = TRUE)
## $data
##
## survived died Total
## A 760 40 800
## B 719 81 800
## Total 1479 121 1600
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## A 1.000000 NA NA
## B 2.135312 1.450752 3.191248
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## A NA NA NA
## B 9.931952e-05 0.0001372591 0.0001554553
##
## $correction
## [1] TRUE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
Das OR beträgt 2.14, das heisst die Chance um zu sterben ist in Spital B mehr als doppelt so hoch wie in Spital A. Das 95% CI schneidet H0 deutlich nicht, der p-Wert ist wiederum gleich wie bei den anderen Analysen.
Fazit: Spital B meiden?!
Nun geht es darum, mögliche Confounding-Variablen zu berücksichtigen. Berechne das Odds Ratio erneut, allerdings stratifiziert nach Risikogruppe. Was stellst du fest?
Tipp: Du brauchst die subset()
-Funktion
Zuerst müssen Teildatensätze und je eine neue 2x2 Tabelle erstellt werden:
<- subset(d.hospital, risk == "low risk")
lowrisk <- subset(d.hospital, risk == "high risk")
highrisk <- table(lowrisk$hospital, lowrisk$death)
tab_lowrisk <- table(highrisk$hospital, highrisk$death)
tab_highrisk tab_lowrisk
##
## survived died
## A 585 15
## B 386 14
tab_highrisk
##
## survived died
## A 175 25
## B 333 67
Nun kann für jedes Stratum die Odds Ratio berechnet werden:
oddsratio(tab_highrisk)
## $data
##
## survived died Total
## A 175 25 200
## B 333 67 400
## Total 508 92 600
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## A 1.000000 NA NA
## B 1.402734 0.8644944 2.340432
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## A NA NA NA
## B 0.173498 0.1876631 0.1731913
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
oddsratio(tab_lowrisk)
## $data
##
## survived died Total
## A 585 15 600
## B 386 14 400
## Total 971 29 1000
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## A 1.000000 NA NA
## B 1.415058 0.6637963 2.998005
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## A NA NA NA
## B 0.3636991 0.4420656 0.3559016
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
In beiden Strata sinkt die Odds Ratio beträchtlich. Auffällig ist auch, dass beide 95% CI’s nun H0 schneiden… Die Variable “risk” scheint also ein wichtiger Confounder zu sein.
Versuche nun, alle potentiellen Confounder zu berücksichtigen. Erstelle dazu einen Teildatensatz, in welchem nur Männer über 60 Jahren und einem hohen Risiko vertreten sind. Was findest du heraus, wenn du die Odds Ratio erneut berechnest?
Tipp: innerhalb der subset()
Funktion kann man mehrere
Bedingungen mit einem &
aneinander knüpfen.
Zuerst wird wieder der Teildatensatz und die 2x2 Tabelle erstellt
<- subset(d.hospital,
high_risk_profile == "male" & risk == "high risk" & age == "60+")
sex <- table(high_risk_profile$hospital, high_risk_profile$death)
tab_high_risk_profile tab_high_risk_profile
##
## survived died
## A 30 10
## B 120 40
Nun die adjustierte Odds Ratio
oddsratio(tab_high_risk_profile)
## $data
##
## survived died Total
## A 30 10 40
## B 120 40 160
## Total 150 50 200
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## A 1.0000000 NA NA
## B 0.9919928 0.4547018 2.3173
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## A NA NA NA
## B 0.984425 1 1
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
Die Odds Ratio beträgt 1. Das heisst, wenn man für alle Confounder kontrolliert, gibt es keinen Unterschied zwischen Spital A und B in Bezug auf die Chance, zu sterben.
Nun soll noch Mantel-Haenszel Methode verwendet werden. Die Funktion
mhor()
befindet sich im Package epiDisplay
.
Die Funktion braucht drei Argumente:
Was ist das Resultat dieser Analyse?
Tipp: Wir müssen alle Confounding-Variablen (sex, age, risk) in eine
Variable bringen (am Schluss sollten \(2*2*2 =
8\) Ausprägungen existieren). Um dies zu erreichen ist z.B. die
paste()
Funktion hilfreich. Hier ein Beispiel:
<- "A"
a <- "B"
b <- "C"
c <- paste(a,b,c, sep = "")
abc abc
## [1] "ABC"
Das sep = ""
definiert, wie die einzelnen Elemente
getrennt werden (in diesem Fall gar nicht)
Zuerst werden alle Confounding-Variablen (sex, age, risk) in eine Variable gebracht:
$profile <- factor(paste(d.hospital$risk,d.hospital$sex, d.hospital$age))
d.hospital<- table(d.hospital$profile, d.hospital$death)
tab tab
##
## survived died
## high risk female <60 95 5
## high risk female 60+ 119 21
## high risk male <60 144 16
## high risk male 60+ 150 50
## low risk female <60 297 3
## low risk female 60+ 144 6
## low risk male <60 245 5
## low risk male 60+ 285 15
Dann können wir die mhor() Funktion anwenden:
library(epiDisplay)
mhor(d.hospital$death, d.hospital$hospital, d.hospital$profile)
##
## Stratified analysis by Var3
## OR lower lim. upper lim. P value
## Var3 high risk female <60 1 0.0800 9.16 1
## Var3 high risk female 60+ 1 0.3313 3.42 1
## Var3 high risk male <60 1 0.3086 3.55 1
## Var3 high risk male 60+ 1 0.4280 2.50 1
## Var3 low risk female <60 1 0.0168 19.43 1
## Var3 low risk female 60+ 1 0.0875 7.26 1
## Var3 low risk male <60 1 0.0199 10.40 1
## Var3 low risk male 60+ 1 0.3011 3.84 1
## M-H combined 1 0.6455 1.55 1
##
## M-H Chi2(1) = 0 , P value = 1
## Homogeneity test, chi-squared 7 d.f. = 0 , P value = 1
Wir sehen, dass für jede separate Strata die Odds Ratio 1 beträgt. Wie oben kommen wir zum Schluss, dass es keinen Unterschied zwischen Spital A und B in Bezug auf die Chance zu sterben gibt, wenn man alle Confounding-Variablen berücksichtigt.