Aprender la forma apropiada de analizar un ECC:
Identificar los métodos estadísticos apropiados para la comparación basal de los dos grupos, de acuerdos a los tipos de variables analizadas.
Identificar los métodos estadísticos apropiados para determinar si existen diferencias estadísticamente significativas de las variables de desenlace entre los diferentes grupos de intervención.
Interpretar apropiadamente los resultados obtenidos.
Al finalizar este módulo, el estudiante estará en la capacidad de analizar e interpretar los resultados estadísticos de un experimento clínico controlado (básico).
En pacientes hospitalizados por COVID-19, evaluar la efectividad y seguridad de rosuvastatina+colchicina, emtricitabina+tenofovir y su uso combinado (a modo de ejemplo solo analizaremos los brazos rosuvastatina+colchicina y estándar clínico de tratamiento).
Se busca evaluar la efectividad de dos tratamientos para bajar de peso: dieta vs dieta + actividad física dirigida, ¿existen diferencias entre los dos tratamientos?
El objetivo de esta tabla es determinar si los grupos de intervención son comparables.
Se utilizan métodos descriptivos para comparar los grupos:
Para recordar: Antes de cualquier análisis, sin importar el tipo de estudio, es preciso hacer un análisis descriptivo de los datos.
¿Qué comparar entre los grupos según la escala de medición de las variables?
La base de datos “datos_ejemplo.txt” contiene la información del estudio y el archivo “Diccionario_ejemplo.xlsx” su diccionario.
# Cambio del directorio de trabajo (ponga la dirección en donde está guardado el archivo)
setwd("G:\\Mi unidad\\UN 2023\\UN 2023-II\\Epidemiologia\\ECA")
# Lectura de los datos
datos1<-read.table("datos_ejemplo.txt",h=T,,sep=",")
# Pacientes por cada brazo de tratamiento
datos1$datos.al_3<-factor(datos1$datos.al_3, labels=c("Colc/Rosu","Estándar"))
table(datos1$datos.al_3)
##
## Colc/Rosu Estándar
## 161 162
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 24.00 47.00 56.00 55.56 64.00 86.00
par(mfrow=c(1,3))
hist(datos1$datos.idemog_19,main="",xlab="Edad (años)",ylab="Frecuencia", freq = F)
curve(dnorm(x, mean = mean(datos1$datos.idemog_19), sd = sd(datos1$datos.idemog_19)), col = 2, lwd = 2, add = TRUE)
boxplot(datos1$datos.idemog_19, ylab="Edad (años)")
qqnorm(datos1$datos.idemog_19, main="", xlab="Percentiles teóricos", ylab="Percentiles muestrales")
qqline(datos1$datos.idemog_19, col=2)
##
## Shapiro-Wilk normality test
##
## data: datos1$datos.idemog_19
## W = 0.99192, p-value = 0.07573
# Edad por brazo
boxplot(datos1$datos.idemog_19~datos1$datos.al_3,xlab="Tratamiento",ylab="Edad (años)")
hist(datos1$datos.idemog_19[datos1$datos.al_3=="Colc/Rosu"],main="Colc/Rosu",xlab="Edad (años)",ylab="Frecuencia",xlim=c(20,90), freq=F)
curve(dnorm(x, mean = mean(datos1$datos.idemog_19[datos1$datos.al_3=="Colc/Rosu"]), sd = sd(datos1$datos.idemog_19[datos1$datos.al_3=="Colc/Rosu"])), col = 2, lwd = 2, add = TRUE)
hist(datos1$datos.idemog_19[datos1$datos.al_3=="Estándar"],main="Estándar",xlab="Edad (años)",ylab="Frecuencia",xlim=c(20,90), freq=F)
curve(dnorm(x, mean = mean(datos1$datos.idemog_19[datos1$datos.al_3=="Estándar"]), sd = sd(datos1$datos.idemog_19[datos1$datos.al_3=="Estándar"])), col = 2, lwd = 2, add = TRUE)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 24.00 47.00 56.00 56.04 66.00 86.00
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 24.00 47.00 56.00 55.09 63.00 84.00
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0000 0.0000 0.0000 0.3158 0.0000 6.0000
##
## 0 1 2 3 4 5 6
## 260 40 15 3 3 1 1
## Charlson por brazo
par(mfrow=c(1,2))
barplot(prop.table(table(datos1$datos.acli_28[datos1$datos.al_3=="Colc/Rosu"])),main="Colc/Rosu",xlab="Charlson",ylab="Frecuencia", xlim=c(0,6), ylim=c(0,0.9))
barplot(prop.table(table(datos1$datos.acli_28[datos1$datos.al_3=="Estándar"])),main="Estándar",xlab="Charlson",ylab="Frecuencia", xlim=c(0,6), ylim=c(0,0.9))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0000 0.0000 0.0000 0.3665 0.0000 6.0000
tcharl_2<-round(rbind(table(datos1$datos.acli_28[datos1$datos.al_3=="Colc/Rosu"]),prop.table(table(datos1$datos.acli_28[datos1$datos.al_3=="Colc/Rosu"]))*100),2)
rownames(tcharl_2)<-c("n","%")
tcharl_2
## 0 1 2 3 4 5 6
## n 125.00 24.00 7.00 2.00 1.00 1.00 1.00
## % 77.64 14.91 4.35 1.24 0.62 0.62 0.62
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0000 0.0000 0.0000 0.2654 0.0000 4.0000
tcharl_4<-round(rbind(table(datos1$datos.acli_28[datos1$datos.al_3=="Estándar"]),prop.table(table(datos1$datos.acli_28[datos1$datos.al_3=="Estándar"]))*100),2)
rownames(tcharl_4)<-c("n","%")
tcharl_4
## 0 1 2 3 4
## n 135.00 16.00 8.00 1.00 2.00
## % 83.33 9.88 4.94 0.62 1.23
\[\text{SMD} = \frac{\bar{x}_{1} - \bar{x}_0}{s_p}\] donde \(\bar{x}_{1}\) y \(\bar{x}_{0}\) son los promedios de la variable a comparar en cada grupo y \(s_p = \sqrt{ \frac{(n_1 - 1)s_1^2 + (n_0 - 1)s_c^2}{n_1 + n_0 - 2} }\) es la desviación estándar conjugada.
Interpretación
|SMD| < 0.1: diferencia despreciable.
0.1<=|SMD|<0.2: diferencia pequeña.
0.2<=|SMD|<0.5: diferencia moderada.
|SMD|>=0.5. diferencia grande.
Para reflexionar: ¿Siempre será adecuado hacer la comparación a partir de este indicador?.
# Sexo
datos1$datos.idemog_2<-factor(datos1$datos.idemog_2,levels = c(1,2), labels=c("Mujer","Hombre"))
table(datos1$datos.idemog_2)
##
## Mujer Hombre
## 101 222
## Sexo por brazo
### Brazo: Colchicina/Rosuvastatina
tsexo_2<-round(rbind(table(datos1$datos.idemog_2[datos1$datos.al_3=="Colc/Rosu"]),prop.table(table(datos1$datos.idemog_2[datos1$datos.al_3=="Colc/Rosu"]))*100),2)
rownames(tsexo_2)<-c("n","%")
tsexo_2
## Mujer Hombre
## n 53.00 108.00
## % 32.92 67.08
### Brazo: Estándar de cuidado
tsexo_4<-round(rbind(table(datos1$datos.idemog_2[datos1$datos.al_3=="Estándar"]),prop.table(table(datos1$datos.idemog_2[datos1$datos.al_3=="Estándar"]))*100),2)
rownames(tsexo_4)<-c("n","%")
tsexo_4
## Mujer Hombre
## n 48.00 114.00
## % 29.63 70.37
#Estrato socioeconómico
## 7: Sin información
datos1$datos.idemog_17[datos1$datos.idemog_17==7]<-NA
datos1$datos.idemog_17<-factor(datos1$datos.idemog_17)
table(datos1$datos.idemog_17)
##
## 1 2 3 4 5 6
## 6 77 133 58 25 13
## Estrato por brazo
### Brazo: Colchicina/Rosuvastatina
testrato_2<-round(rbind(table(datos1$datos.idemog_17[datos1$datos.al_3=="Colc/Rosu"]),prop.table(table(datos1$datos.idemog_17[datos1$datos.al_3=="Colc/Rosu"]))*100),2)
rownames(testrato_2)<-c("n","%")
testrato_2
## 1 2 3 4 5 6
## n 1.00 39 73.00 23.00 13.00 7.00
## % 0.64 25 46.79 14.74 8.33 4.49
### Brazo: Estándar de cuidado
testrato_4<-round(rbind(table(datos1$datos.idemog_17[datos1$datos.al_3=="Estándar"]),prop.table(table(datos1$datos.idemog_17[datos1$datos.al_3=="Estándar"]))*100),2)
rownames(testrato_4)<-c("n","%")
testrato_4
## 1 2 3 4 5 6
## n 5.00 38.00 60.00 35.00 12.00 6.00
## % 3.21 24.36 38.46 22.44 7.69 3.85
\[\text{SMD} = \frac{p_{1} - p_0}{\sqrt{p(1-p)}}\]
donde \(p_{1}\) y \(p_{0}\) son las proporciones de una categoría de la variable a comparar en cada grupo y \(p\) es la proporción en toda la muestra.
Interpretación
|SMD| < 0.1: diferencia despreciable.
0.1<=|SMD|<0.2: diferencia pequeña.
0.2<=|SMD|<0.5: diferencia moderada.
|SMD|>=0.5. diferencia grande.
Ejercicio: Escoger 4 variables de la base de datos y hacer la comparación correspondiente.
suppressMessages(suppressWarnings(library(compareGroups)))
# method = NA: utiliza la prueba de Shapiro Wilk para tomar la decisión
baseline <- compareGroups(datos.al_3 ~ datos.idemog_2 + datos.idemog_19 + datos.idemog_17 + datos.acli_28, data = datos1, method = NA, include.label= T)
## Warning in chisq.test(xx, correct = FALSE): Chi-squared approximation may be
## incorrect
## Warning in chisq.test(xx, correct = FALSE): Chi-squared approximation may be
## incorrect
## Warning in chisq.test(xx, correct = FALSE): Chi-squared approximation may be
## incorrect
## Warning in chisq.test(xx, correct = FALSE): Chi-squared approximation may be
## incorrect
## Warning in chisq.test(xx, correct = FALSE): Chi-squared approximation may be
## incorrect
##
##
## -------- Summary of results by groups of 'datos.al_3'---------
##
##
## var N p.value method selection
## 1 datos.idemog_2 323 0.605 categorical ALL
## 2 datos.idemog_19 323 0.505 continuous normal ALL
## 3 datos.idemog_17 312 0.266 categorical ALL
## 4 datos.acli_28 323 0.215 continuous non-normal ALL
## -----
## Signif. codes: 0 '**' 0.05 '*' 0.1 ' ' 1
##
## --------Summary descriptives table by 'datos.al_3'---------
##
## __________________________________________________
## Colc/Rosu Estándar
## N=161 N=162
## ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
## datos.idemog_2:
## Mujer 53 (32.9%) 48 (29.6%)
## Hombre 108 (67.1%) 114 (70.4%)
## datos.idemog_19 56.0 (13.1) 55.1 (12.5)
## datos.idemog_17:
## 1 1 (0.64%) 5 (3.21%)
## 2 39 (25.0%) 38 (24.4%)
## 3 73 (46.8%) 60 (38.5%)
## 4 23 (14.7%) 35 (22.4%)
## 5 13 (8.33%) 12 (7.69%)
## 6 7 (4.49%) 6 (3.85%)
## datos.acli_28 0.00 [0.00;0.00] 0.00 [0.00;0.00]
## ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Dadas \(X_1,X_2,...,X_{n_1}\) una muestra aleatoria de una población \(N(\mu_1, \sigma_1^2)\) y \(Y_1,Y_2,...,Y_{n_2}\) una muestra aleatoria de una población \(N(\mu_2, \sigma_2^2)\), independientes, se tienen los siguientes sistemas de hipótesis y test:
En caso de querer probar sobre la igualdad de las medias de las dos poblaciones, se toma \(\delta_0=0\)
Supongamos que la efectividad de los tratamientos (dieta vs dieta + ejercicio) se evaluó a través de la diferencia entre el peso antes y el peso después, de tal forma que el sistema de hipótesis a contrastar es:
\[H_0:\mu_1-\mu2=0\text{ vs }H_1:\mu_1-\mu2\neq 0\]
Donde \(\mu_1\) es el valor esperado de la diferencia entre el peso antes y después para el grupo de solo dieta y \(\mu_2\) es el valor esperado de la diferencia entre el peso antes y después para el grupo de dieta y ejercicio.
#simulación de los pesos para los dos grupos
#grupo de solo dieta
set.seed(0)
dif1<-rnorm(150,0.8,1)
#grupo dieta + ejercicio
set.seed(0)
dif2<-rnorm(150,2,1.2)
boxplot(dif1,dif2, xlab="Tratamiento (dieta vs dieta+ejercicio)", ylab="Diferencia en Kg")
##
## Welch Two Sample t-test
##
## data: dif1 and dif2
## t = -10.414, df = 288.61, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -1.4136831 -0.9642431
## sample estimates:
## mean of x mean of y
## 0.7448154 1.9337785
La prueba de Mann-Whitney-Wilcoxon es una prueba no paramétrica que permite compara dos poblaciones en términos de una variable, medida como mínimo en escala ordinal, por medio de sus medianas. Dadas las muestras \(X_1,X_2,...,X_{n_1}\) y \(Y_1,Y_2,...,Y_{n_2}\) con medianas \(\theta_1\) y \(\theta_2\) respectivamente, la prueba de Mann-Whitney-Wilcoxon permite contrastar los siguientes sistemas de hipótesis:
En caso de contar con menos muestra y que no se verifique el supuesto de normalidad, se podría evaluar si los dos tratamientos son diferentes en efectividad con respecto a las medianas:
\[H_0:\theta_1=\theta_2\text{ vs }H_1:\theta_1\neq\theta_2\]
Donde \(F\) representa la distribución de la diferencia de peso en el grupo de solo dieta y \(G\) la distribución de la diferencia de peso en el grupo de dieta y ejercicio.
set.seed(0)
#simulación para el grupo de dieta
diff1<-rchisq(30,df=1)
#simulación para el grupo de dieta y ejercicio
diff2<-rchisq(30,df=2)
boxplot(diff1,diff2, xlab="Tratamiento (dieta vs dieta+ejercicio)", ylab="Diferencia en Kg")
##
## Wilcoxon rank sum exact test
##
## data: diff1 and diff2
## W = 274, p-value = 0.008774
## alternative hypothesis: true location shift is not equal to 0
La prueba de independencia ji-cuadrado se utiliza cuando se quiere probar si existe relación entre dos variables categóricas (\(X\) y \(Y\)), de tal forma que el sistema de hipótesis está dado por:
\[H_0:\text{No existe asociación entre la intervención y el desenlace }(RR=1)\] \[\text{frente a}\] \[H_1:\text{Existe asociación entre la intervención y el desenlace }(RR\neq1) \] Sea \(k\) el número de categorías de \(X\) y \(p\) el número de categorías de \(Y\), el estadístico de prueba está dado por:
\[\chi^2_c=\sum_{i=1}^{k}\sum_{j=1}^{p}\frac{(n_{ij}-e_{ij})^2}{e_{ij}}\] donde \(n_{ij}\) es el número de elementos que pertencen a la \(i\)-ésima categoría de \(X\) y a la \(j\)-ésima categoría de \(Y\), y \(e_{ij}=\frac{n_{i\bullet}n_{\bullet j}}{n_{\bullet\bullet}}\) es la frecuencia esperada bajo independencia.
El test está dado por:
\[\tau:\text{Rechazar }H_0\text{ si }\chi^2_c>\chi^2_{1-\alpha}(v), v=(k-1)\times (p-1)\] donde \(\chi^2_{1-\alpha}(v)\) es el percentil \(1-\alpha\) de una distribución ji-cuadrado con \(v\) grados de libertad.
Observación
Esta prueba se utiliza cuando todos los \(e_{ij}>5\).
Se seleccionó una muestra de nacimientos para determinar si existe asociación entre el consumo de alcohol y la presencia o ausencia de bajo peso al nacer. Con base en los resultados de la tabla. Con un 10% de significancia, ¿qué puede concluir?
\(X\): Consumo de alcohol durante el embarazo \(Y\): Peso al nacer
\(X / Y\) | Bajo peso:Si | Bajo peso:No | Total |
---|---|---|---|
Si | 35 | 25 | 60 |
No | 40 | 100 | 140 |
El sistema de hipótesis está dado por:
\[H_0:\text{No existe asociación entre el consumo de alcohol y el bajo peso al nacer}\] \[\text{frente a}\] \[H_1:\text{Existe asociación entre el consumo de alcohol y el bajo peso al nacer}\]
#tabla de frecuencias
tabla<-matrix(c(35,25,40,100),byrow = T,nc=2,nr=2)
colnames(tabla)<-c("Bajo peso: Si","Bajo peso:No")
row.names(tabla)<-c("Alcohol: Si", "Alcohol: No")
print(tabla)
## Bajo peso: Si Bajo peso:No
## Alcohol: Si 35 25
## Alcohol: No 40 100
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tabla
## X-squared = 14.629, df = 1, p-value = 0.0001309
## Bajo peso: Si Bajo peso:No
## Alcohol: Si 22.5 37.5
## Alcohol: No 52.5 87.5
Como valor p\(=0.00013<\alpha=0.1\), existe asociación entre el consumo de alcohol y el bajo peso al nacer.
Se utiliza cuando los \(e_{ij}\leq5\), el sistema de hipótesis está dado por:
\[H_0:\text{No existe asociación entre la intervención y el desenlace }(RR=1)\]
\[\text{frente a}\] \[H_1:\text{Existe asociación entre la intervención y el desenlace }(RR\neq1) \]
Supongamos el problema del ejemplo anterior, pero con los siguientes resultados:
\(X / Y\) | Bajo peso:Si | Bajo peso:No | Total |
---|---|---|---|
Si | 35 | 25 | 60 |
No | 40 | 100 | 140 |
#tabla de frecuencias
tabla<-matrix(c(5,25,3,50),byrow = T,nc=2,nr=2)
colnames(tabla)<-c("Bajo peso: Si","Bajo peso:No")
row.names(tabla)<-c("Alcohol: Si", "Alcohol: No")
print(tabla)
## Bajo peso: Si Bajo peso:No
## Alcohol: Si 5 25
## Alcohol: No 3 50
## Warning in chisq.test(tabla): Chi-squared approximation may be incorrect
## Bajo peso: Si Bajo peso:No
## Alcohol: Si 2.891566 27.10843
## Alcohol: No 5.108434 47.89157
##
## Fisher's Exact Test for Count Data
##
## data: tabla
## p-value = 0.1307
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
## 0.5846555 22.8454819
## sample estimates:
## odds ratio
## 3.281417
\[H_0:\text{No existe asociación entre la intervención y el desenlace (mortalidad) }(RR=1)\] \[\text{frente a}\] \[H_1:\text{Existe asociación entre la intervención y el desenlace (mortalidad)}(RR\neq1) \]
datos1$y<-factor(datos1$y, labels=c("Muerte (No)","Muerte (Si)"))
tab<-table(datos1$datos.al_3,datos1$y)
tab
##
## Muerte (No) Muerte (Si)
## Colc/Rosu 113 48
## Estándar 115 47
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tab
## X-squared = 0.00129, df = 1, p-value = 0.9713
La función “epi.2by2” permite calcular medidas de asociación para diferentes tipos de estudio cuya exposición y desenlace sean dicotómicos. En particular, para un ensayo clínico de estas características la tabla resultante sería:
Trat/Desenlace | Si | No | Total |
---|---|---|---|
Si | \(n_{11}\) | \(n_{12}\) | \(n_{1\bullet}\) |
No | \(n_{21}\) | \(n_{22}\) | \(n_{2\bullet}\) |
:—————: | :——-: | :——-: | :————–: |
Total | \(n_{\bullet1}\) | \(n_{\bullet2}\) | \(n\) |
## Loading required package: survival
## Package epiR 2.0.58 is loaded
## Type help(epi.about) for summary information
## Type browseVignettes(package = 'epiR') to learn how to use epiR for applied epidemiological analyses
##
##
## Muerte (No) Muerte (Si)
## Colc/Rosu 113 48
## Estándar 115 47
# Debemos cambiar el orden de las columnas de la tabla para utilizar la función, teniendo en cuenta que: method = "cohort.count"
tab<-cbind(tab[,2],tab[,1])
colnames(tab)<-c("Muerte (Si)","Muerte (No)")
tab
## Muerte (Si) Muerte (No)
## Colc/Rosu 48 113
## Estándar 47 115
epi.2by2(dat = tab, method ="cohort.count",
conf.level = 0.95, units = 100, outcome = "as.columns", interpret=F)
## Outcome + Outcome - Total Inc risk *
## Exposed + 48 113 161 29.81 (22.87 to 37.52)
## Exposed - 47 115 162 29.01 (22.16 to 36.65)
## Total 95 228 323 29.41 (24.50 to 34.71)
##
## Point estimates and 95% CIs:
## -------------------------------------------------------------------
## Inc risk ratio 1.03 (0.73, 1.44)
## Odds ratio 1.04 (0.64, 1.68)
## Attrib risk in the exposed * 0.80 (-9.14, 10.74)
## Attrib fraction in the exposed (%) 2.69 (-36.43, 30.59)
## Attrib risk in the population * 0.40 (-8.18, 8.97)
## Attrib fraction in the population (%) 1.36 (-17.01, 16.84)
## -------------------------------------------------------------------
## Uncorrected chi2 test that OR = 1: chi2(1) = 0.025 Pr>chi2 = 0.874
## Fisher exact test that OR = 1: Pr>chi2 = 0.903
## Wald confidence limits
## CI: confidence interval
## * Outcomes per 100 population units
Barón F.J. Bioestadística. Universidad de Málaga. http://www.bioestadistica.uma.es/baron/bioestadistica.pdf
Corzo, J. A. (2005). Notas de clase. Estadística no paramétrica (Métodos basados en rangos). Universidad Nacional de Colombia. Departamento de Estadística.
Mayorga J.H. (2004). Inferencia estadística. Universidad Nacional de Colombia. Departamento de Estadística.