En esta actividad realizaremos un Análisis de la Varianza Univariante (ANOVA) y Multivariante (MANOVA) sobre el conjunto de datos “geneData” del paquete “Biobase”.
suppressPackageStartupMessages(library(Biobase)) # suprimir los outputs
suppressPackageStartupMessages(library(car)) # suprimir los outputs
library(readxl) # cargamos libreria
library("biotools")
## Cargando paquete requerido: MASS
## ---
## biotools version 4.3
library(Biobase) # cargamos libreria
library(car) # cargamos libreria
data(geneData)
Datos_T <- t(geneData) # transpuesta
df_factor <- read_excel("tipos_cancer.xlsx") # leemos los Factors o Grupos para aplicar luego a los datos
cancer <- factor(df_factor$`factor`, levels = 1:3,labels = c('colon','lung','liver'))
## FUNCIONES ##
################################################Verificacion_Homocedasticidad##############################################
Verificacion_Homocedasticidad <- function(Numero_gen,cancer){
resultado <- leveneTest(geneData[Numero_gen,],cancer,center=mean)$`Pr(>F)`[1]
valores <- as.numeric(unlist(resultado))
if (all(valores > 0.05)){
print(paste("El Gen", Numero_gen, "es Homocedastico en todos los grupos."))
cat("\n\n")
resultado <- leveneTest(geneData[Numero_gen,],cancer,center=mean)
print(resultado)
}
else{
print(paste("El Gen", Numero_gen, "es Heterocedastico en todos los grupos."))
cat("\n\n")
print(resultado)
}
}
##############################################Verificacion_de_Normalidad##################################################
Verificacion_de_Normalidad <- function(Numero_gen) {
resultado <- by(geneData[Numero_gen,], INDICES = cancer, FUN = function(x) shapiro.test(x)$p.value)
valores <- as.numeric(unlist(resultado))
if (all(valores > 0.05)){
print(paste("El Gen", Numero_gen, "cumple con Normalidad en todos los grupos, utilizaremos un TEST Paramétrico"))
print(resultado)
TRUE
}
else{
print(paste("El Gen", Numero_gen, "NO cumple con Normalidad en todos los grupos, utilizaremos un TEST No Paramétrico"))
print(resultado)
FALSE
}
}
##########################################Verificacion_de_Normalidad_MULTIVARIANTE########################################
Verificacion_de_Normalidad_MULTIVARIANTE <- function(df) {
cat("\n\n\n")
res_test_mardia <- mvn(data = df, mvn_test = "mardia")
print(res_test_mardia$multivariate_normality)
cat("\n\n\n")
res_test_royston <- mvn(data = df, mvn_test = "royston")
print(res_test_royston$multivariate_normality)
cat("\n\n\n")
res_test_hz <- mvn(data = df, mvn_test = "hz")
print(res_test_hz$multivariate_normality)
}
########################################Verificacion_de_Normalidad_BOOLEAN##############################
Verificacion_de_Normalidad_BOOLEAN <- function(Numero_gen) {
resultado <- by(geneData[Numero_gen,], INDICES = cancer, FUN = function(x) shapiro.test(x)$p.value)
valores <- as.numeric(unlist(resultado))
if (all(valores > 0.05)){
TRUE
}
else{
FALSE
}
}
#########################################################################################################
MANOVA_para_Cada_PAR_GRUPOS <- function(df) {
manova_result <- manova(as.matrix(df[, 1:4]) ~ cancer_col, data = df)
cat("\n\n")
print(summary(manova_result, test = "Pillai"))
par(mfrow = c(2,2))
cat("\n\n")
anova_genes <- summary.aov(manova_result)
print(anova_genes)
for (gen in colnames(df)[1:4]) {
boxplot(
df[[gen]] ~ df$cancer_col,
main = gen,
col = c("red", "blue","green"),
ylab = "Expresión"
)
}
par(mfrow = c(1,1))
}
Hipótesis nula (H₀):
La distribucion de los datos sí sigue una distribución
normal.
Hipótesis alternativa (H₁):
La distribucion de los datos no sigue una distribución
normal.
Si el p-valor < 0.05 rechazamos la hipótesis nula. Esto indica que los datos no siguen una distribución normal.
Hipótesis nula (H₀):
La datos sí son homocedasticos entre los 3 tipos de
cáncer
Hipótesis alternativa (H₁):
La datos NO son homocedasticos entre los 3 tipos de
cáncer
Si tienen un p_valor < 0.05 podremos rechazar la Ho, asi que los datos no son homocedásticos entre los 3 grupos de cancer.**
Verificacion_de_Normalidad(99)
## [1] "El Gen 99 cumple con Normalidad en todos los grupos, utilizaremos un TEST Paramétrico"
## cancer: colon
## [1] 0.8378222
## ------------------------------------------------------------
## cancer: lung
## [1] 0.7080293
## ------------------------------------------------------------
## cancer: liver
## [1] 0.6562811
## [1] TRUE
Verificacion_Homocedasticidad(99,cancer)
## [1] "El Gen 99 es Heterocedastico en todos los grupos."
##
##
## [1] 0.02893275
-Como el Gen99 cumple con Normalidad en todos los grupos y es Heterocedástico con p_valor = 0.02893275 , aplicaremos un Test Anova Parametrico Heterocedastico.
anova_99 <- oneway.test(geneData[99,]~cancer)
anova_99
##
## One-way analysis of means (not assuming equal variances)
##
## data: geneData[99, ] and cancer
## F = 28.474, num df = 2.000, denom df = 11.746, p-value = 3.127e-05
-Nos devuelve un p-valor < 0.05, por lo que podemos evidenciar que existen diferencias estadísticamente significativas en el valor promedio de expresión del GEN99 entre al menos dos grupos. Sin embargo, este resultado no indica entre qué grupos concretos se producen dichas diferencias. Por ello, aplicamos un contraste post hoc. Como los datos siguen una distribución normal, aplicaremos el test pairwise.t.test().
Como los grupos siguen una distribucion normal usamos un t.test().
pairwise.t.test(geneData[99,],cancer,p.adjust = "fdr") # Aplicamos una correcion por múltiples contrastes
##
## Pairwise comparisons using t tests with pooled SD
##
## data: geneData[99, ] and cancer
##
## colon lung
## lung 0.0021 -
## liver 0.0398 1.5e-05
##
## P value adjustment method: fdr
layout(matrix(1:2, ncol = 2)); cols = c("blue","red","green","black")
boxplot(geneData[99,]~cancer, col = cols[1:3])
-Entre las distintas comparaciones se observan diferencias, aunque algunas son más significativas que otras. Por ejemplo, la comparación Pulmón–Hígado muestra una mayor separación entre grupos, evidenciando diferencias más marcadas. En cambio, en la comparación Colon–Pulmón las medias se encuentran más próximas. Asimismo, la comparación Colon–Hígado presenta un p-valor de 0.0398, ligeramente inferior al umbral de significación de 0.05.
Verificacion_de_Normalidad(444)
## [1] "El Gen 444 cumple con Normalidad en todos los grupos, utilizaremos un TEST Paramétrico"
## cancer: colon
## [1] 0.5179257
## ------------------------------------------------------------
## cancer: lung
## [1] 0.4823558
## ------------------------------------------------------------
## cancer: liver
## [1] 0.9947356
## [1] TRUE
Verificacion_Homocedasticidad(444,cancer)
## [1] "El Gen 444 es Heterocedastico en todos los grupos."
##
##
## [1] 0.01587498
anova_444 <- oneway.test(geneData[444,]~cancer)
anova_444
##
## One-way analysis of means (not assuming equal variances)
##
## data: geneData[444, ] and cancer
## F = 0.22167, num df = 2.000, denom df = 12.038, p-value = 0.8044
Nos devuelve un p-valor = 0.80 > 0.05, por lo que no existen evidencias suficientes en la expresión del GEN444 para afirmar que las medias difieren entre los grupos.
Como los grupos siguen una distribucion normal usamos un t.test().
pairwise.t.test(geneData[444,],cancer,p.adjust = "fdr") # Aplicamos una correcion por múltiples contrastes
##
## Pairwise comparisons using t tests with pooled SD
##
## data: geneData[444, ] and cancer
##
## colon lung
## lung 0.78 -
## liver 0.78 0.78
##
## P value adjustment method: fdr
layout(matrix(1:2, ncol = 2)); cols = c("blue","red","green","black")
boxplot(geneData[444,]~cancer, col = cols[1:3])
El análisis gráfico corrobora que no existen diferencias entre los grupos, ya que las medias representadas en el boxplot se encuentran prácticamente a la misma altura.
Verificacion_de_Normalidad(10)
## [1] "El Gen 10 NO cumple con Normalidad en todos los grupos, utilizaremos un TEST No Paramétrico"
## cancer: colon
## [1] 0.7022884
## ------------------------------------------------------------
## cancer: lung
## [1] 0.5306949
## ------------------------------------------------------------
## cancer: liver
## [1] 0.01982083
## [1] FALSE
Verificacion_Homocedasticidad(10,cancer)
## [1] "El Gen 10 es Homocedastico en todos los grupos."
##
##
## Levene's Test for Homogeneity of Variance (center = mean)
## Df F value Pr(>F)
## group 2 1.0533 0.365
## 23
-El Gen10 NO cumple con Normalidad en todos los grupos y es HOMOCEDÁSTICO con p_valor = 0.365 , aplicaremos un Test Anova NO Parametrico, ya que algunos de los grupos (LIVER cancer )no cumplen con los supuestos de normalidad aplicado en el test Shapiro-Wilk ya que son < 0.05. Los test no Paramétricos No requiere normalidad, se ordenan los datos independientemente del grupo y se calculan sus rangos, luego se compara la suma de los rango de cada grupos con el rango medio total
kruskal.test(geneData[10,]~cancer)
##
## Kruskal-Wallis rank sum test
##
## data: geneData[10, ] by cancer
## Kruskal-Wallis chi-squared = 2.6949, df = 2, p-value = 0.2599
-Tenemos un p-valor = 0.2599 > 0.05, por lo que se afirma que NO existen diferencias significativas entre los grupos. Aplicamos el test pairwise.wilcox.test(), ya que los grupos NO cumplen el requisito de normalidad, es decir, tras un ANOVA no paramétrico.
pairwise.wilcox.test(geneData[10,],cancer,p.adjust = "fdr")
##
## Pairwise comparisons using Wilcoxon rank sum exact test
##
## data: geneData[10, ] and cancer
##
## colon lung
## lung 0.57 -
## liver 0.57 0.30
##
## P value adjustment method: fdr
-Obervando la comparación entre grupos con el test Wilcox vemos que para cada grupo existe un p_valor > 0.05, asio que podemos afirmar estadisticamente y en la representación gráfica de los boxplot que NO existe diferencias significativas entre los grupos.
layout(matrix(1:2, ncol = 2)); cols = c("blue","red","green","black")
boxplot(geneData[10,]~cancer, col = cols[1:3])
-El análisis gráfico corrobora que no existen diferencias entre los grupos, ya que las medianas representadas en el boxplot se encuentran prácticamente a la misma altura.
Verificacion_de_Normalidad(383)
## [1] "El Gen 383 NO cumple con Normalidad en todos los grupos, utilizaremos un TEST No Paramétrico"
## cancer: colon
## [1] 0.001367186
## ------------------------------------------------------------
## cancer: lung
## [1] 0.007808888
## ------------------------------------------------------------
## cancer: liver
## [1] 0.01630456
## [1] FALSE
Verificacion_Homocedasticidad(383,cancer)
## [1] "El Gen 383 es Homocedastico en todos los grupos."
##
##
## Levene's Test for Homogeneity of Variance (center = mean)
## Df F value Pr(>F)
## group 2 0.8911 0.4239
## 23
-El Gen383 NO cumple con Normalidad en todos los grupos y es HOMOCEDÁSTICO , aplicaremos un Test Anova NO Parametrico. Ya que algunos de los grupos no cumplen con los supuestos de normalidad aplicado en el test Shapiro-Wilk ya que son < 0.05
kruskal.test(geneData[383,]~cancer)
##
## Kruskal-Wallis rank sum test
##
## data: geneData[383, ] by cancer
## Kruskal-Wallis chi-squared = 5.3274, df = 2, p-value = 0.06969
-Tras aplicar Kruskal-Wallis, tenemos un p-valor = 0.06969 > 0.05, por lo que se afirma que NO existen diferencias significativas entre algunos los grupos. Aplicamos el test pairwise.wilcox.test() para estudiar los demás grupos, además los grupos NO cumplen el requisito de normalidad, por eso aplicamos un ANOVA no paramétrico.
pairwise.wilcox.test(geneData[383,],cancer,p.adjust = "fdr")
##
## Pairwise comparisons using Wilcoxon rank sum exact test
##
## data: geneData[383, ] and cancer
##
## colon lung
## lung 0.047 -
## liver 0.721 0.305
##
## P value adjustment method: fdr
-Estadísticamente podemos afirmar que solo existe diferencias significativas entre los grupos COLON-LUNG para el GEN383, aunque está muy cerca del umbral de significación, podremos afirmar que difieren entre sí.
layout(matrix(1:2, ncol = 2)); cols = c("blue","red","green","black")
boxplot(geneData[383,]~cancer, col = cols[1:3])
-La interpretación del gráfico junto a los p_values del WILCOX Test, podemos apreciar que para el grupo COLON-Liver y LUNG-LIVER no existen diferencias significativas con p_valores 0.721 y 0.305 resptv. Sí existen diferencias en los grupos LUNG-COLON aunque este p_valor de 0.047 esta en el umbral de significación.
| GEN | Normalidad | Homocedasticidad | Diferencias entre grupos |
|---|---|---|---|
| 99 | Sí | No | Sí |
| 444 | Sí | No | No |
| 10 | No | Sí | No |
| 383 | No | Sí | No* |
* Para el gen 383 solo se detectan diferencias entre los grupos LUNG-COLON, con un p_valor cercano al umbral de significación.
library(DT)
library(MVN)
casos_estudio = c(10,99,383,444)
genes_subset <- Datos_T[,casos_estudio]
head(genes_subset)
## AFFX-BioDn-5_at 31338_at 31622_f_at 31683_at
## A 10.91870 8.93417 1695.75 52.3302
## B 16.17890 4.28296 2062.22 11.1847
## C 10.14950 11.34340 1648.93 55.6966
## D 9.73639 13.89760 1160.22 59.5886
## E 16.90280 13.88210 2773.18 48.8611
## F 5.33328 16.39860 1361.44 62.3684
Verificacion_de_Normalidad_MULTIVARIANTE(genes_subset)
##
##
##
## Test Statistic p.value Method MVN
## 1 Mardia Skewness 55.900 <0.001 asymptotic ✗ Not normal
## 2 Mardia Kurtosis 2.845 0.004 asymptotic ✗ Not normal
##
##
##
## Test Statistic p.value Method MVN
## 1 Royston 25.498 <0.001 asymptotic ✗ Not normal
##
##
##
## Test Statistic p.value Method MVN
## 1 Henze-Zirkler 1.411 <0.001 asymptotic ✗ Not normal
multivariate_diagnostic_plot(genes_subset,type = c("qq"))
Podemos observar que los test aplicados establecen un p-valor menor a 0.05, por lo que rechazamos la hipótesis nula. Esto indica que los datos no siguen una distribución normal.
Representamos la información de forma visual mediante un QQ plot, lo que nos permite apreciar intuitivamente la distribución de los datos y comparar su comportamiento con el valor teórico de normalidad. Cuanto más se aproximen los puntos (valores observados) a la recta (valores teóricos), más seguros podremos estar que siguen una distribución normal.
boxM(genes_subset[, c(1,2,3,4)], cancer)
##
## Box's M-test for Homogeneity of Covariance Matrices
##
## data: genes_subset[, c(1, 2, 3, 4)]
## Chi-Sq (approx.) = 41.368, df = 20, p-value = 0.003341
Al tener un p_valor < 0.05 podremos rechazar la Ho, asi que los datos no son homocedásticos entre los 3 grupos de cáncer
Como nuestros datos no siguen una distribución Normal y no son Homocedásticos aplicaremos un Manova Paramétrico Pillai que es el menos susceptible ante violaciones de Normalidad y Homocedasticidad.
library(MANOVA.RM)
manova_result <- manova(as.matrix(genes_subset)~cancer)
summary(manova_result,test ="Pillai")
## Df Pillai approx F num Df den Df Pr(>F)
## cancer 2 0.63804 2.4595 8 42 0.02778 *
## Residuals 23
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Para el test Pillai podemos ver que el p_valor = 0.02778 y es altamente significativo. El MANOVA indica que, considerando todas las variables de forma conjunta, hay diferencias significativas entre los grupos de cáncer, pero no nos dice cuáles genes específicos son distintos entre grupos. El Pillai_value=0.63804, valor comprendido entre 0 y 1, cuanto más cerca a 0, mayor separación entre los grupos.
Nos preguntamos, ¿ Qué grupos son diferentes entre sí? y ¿Què variables dependientes son las reponsables de las diferencias?
Para nuestro estudio no es necesario estandarizar los datos, ya que las pruebas estadísticas en las que se apoya se fundamentan en la comparación entre la proporción de varianza explicada por el modelo y la varianza residual.
genes_subset_df <- data.frame(genes_subset, cancer_col = cancer) # añadimo una columna más a nuestro dataframe llamada cancer_col, que es el factor para cada individuo
head(genes_subset_df)
## AFFX.BioDn.5_at X31338_at X31622_f_at X31683_at cancer_col
## A 10.91870 8.93417 1695.75 52.3302 colon
## B 16.17890 4.28296 2062.22 11.1847 liver
## C 10.14950 11.34340 1648.93 55.6966 lung
## D 9.73639 13.89760 1160.22 59.5886 lung
## E 16.90280 13.88210 2773.18 48.8611 lung
## F 5.33328 16.39860 1361.44 62.3684 lung
for (factor in c("lung","colon","liver")){
if (factor=="lung"){
print(paste("Grupo COLON-LIVER"))
}
if (factor=="colon"){
print(paste("Grupo LUNG-LIVER"))
}
if (factor=="liver"){
print(paste("Grupo LUNG-Colon"))
}
subset_filtrado <- genes_subset_df[genes_subset_df$cancer_col != factor, ]
# pasamos como parámetro a la función un **SUBSET_filtrado** donde se suprimen las instancias donde factor != "Lung" o "COLON" o "Liver", de este modo haremos MANOVA por pares
# la funcion hará un MANOVA para cada par y realizará un BOXPLOT, mostrando qué variables influyen en las diferencias que hubieran entre grupos
MANOVA_para_Cada_PAR_GRUPOS(subset_filtrado)
}
## [1] "Grupo COLON-LIVER"
##
##
## Df Pillai approx F num Df den Df Pr(>F)
## cancer_col 1 0.22774 0.81099 4 11 0.5437
## Residuals 14
##
##
## Response AFFX.BioDn.5_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 7.0 6.997 0.0277 0.8702
## Residuals 14 3536.8 252.626
##
## Response X31338_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 77.705 77.705 3.543 0.08075 .
## Residuals 14 307.048 21.932
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Response X31622_f_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 6301 6301 0.0081 0.9296
## Residuals 14 10907747 779125
##
## Response X31683_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 18.5 18.46 0.0538 0.8199
## Residuals 14 4802.4 343.03
## [1] "Grupo LUNG-LIVER"
##
##
## Df Pillai approx F num Df den Df Pr(>F)
## cancer_col 1 0.62901 5.5104 4 13 0.00808 **
## Residuals 16
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Response AFFX.BioDn.5_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 80.03 80.033 0.4546 0.5098
## Residuals 16 2817.03 176.065
##
## Response X31338_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 573.18 573.18 24.757 0.0001375 ***
## Residuals 16 370.44 23.15
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Response X31622_f_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 1053364 1053364 1.4577 0.2448
## Residuals 16 11561565 722598
##
## Response X31683_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 84.0 84.044 0.3003 0.5913
## Residuals 16 4478.6 279.911
## [1] "Grupo LUNG-Colon"
##
##
## Df Pillai approx F num Df den Df Pr(>F)
## cancer_col 1 0.75668 10.107 4 13 0.0006059 ***
## Residuals 16
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Response AFFX.BioDn.5_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 37.92 37.919 0.3434 0.566
## Residuals 16 1766.50 110.406
##
## Response X31338_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 214.605 214.605 45.655 4.607e-06 ***
## Residuals 16 75.209 4.701
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Response X31622_f_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 888612 888612 2.5129 0.1325
## Residuals 16 5657873 353617
##
## Response X31683_at :
## Df Sum Sq Mean Sq F value Pr(>F)
## cancer_col 1 21.51 21.512 0.3074 0.5869
## Residuals 16 1119.64 69.977
Aplicamos un test Pairwise para identificar qué grupos son diferentes entre sí para cada uno de los genes.
Analizamos cada una de las variables mediante un bucle; si en conjunto siguen una distribución normal, aplicamos el test paramétrico pairwise.t.test. En caso contrario, utilizamos el test no paramétrico pairwise.wilcox.test.
for (gen in colnames(genes_subset)){
if(Verificacion_de_Normalidad_BOOLEAN(gen)==TRUE){
print(paste("pairwise.t.test para GEN", gen))
print(pairwise.t.test(genes_subset[,gen], cancer, p.adjust.method = "fdr")) # PARAMETRICO
cat("\n\n\n")
} else{
print(paste("pairwise.wilcox.test para GEN", gen))
print(pairwise.wilcox.test(genes_subset[,gen], cancer, p.adjust.method = "fdr")) # No paramétrico
cat("\n\n\n")
}
}
## [1] "pairwise.wilcox.test para GEN AFFX-BioDn-5_at"
##
## Pairwise comparisons using Wilcoxon rank sum exact test
##
## data: genes_subset[, gen] and cancer
##
## colon lung
## lung 0.57 -
## liver 0.57 0.30
##
## P value adjustment method: fdr
##
##
##
## [1] "pairwise.t.test para GEN 31338_at"
##
## Pairwise comparisons using t tests with pooled SD
##
## data: genes_subset[, gen] and cancer
##
## colon lung
## lung 0.0021 -
## liver 0.0398 1.5e-05
##
## P value adjustment method: fdr
##
##
##
## [1] "pairwise.wilcox.test para GEN 31622_f_at"
##
## Pairwise comparisons using Wilcoxon rank sum exact test
##
## data: genes_subset[, gen] and cancer
##
## colon lung
## lung 0.047 -
## liver 0.721 0.305
##
## P value adjustment method: fdr
##
##
##
## [1] "pairwise.t.test para GEN 31683_at"
##
## Pairwise comparisons using t tests with pooled SD
##
## data: genes_subset[, gen] and cancer
##
## colon lung
## lung 0.78 -
## liver 0.78 0.78
##
## P value adjustment method: fdr
par(mfrow= c(1,2))
for (columna in colnames(genes_subset)){
boxplot(genes_subset[, columna]~cancer,main = columna,col = c("blue", "red", "green"),ylab = "Expresión",cex.main = 0.8)
}