Introducción general

En estas prácticas se utilizarán datos experimentales reales del área de virología e imagenología para ilustrar el flujo completo de análisis con pruebas estadísticas paramétricas:

En ambos casos se seguirá la misma lógica:

  1. Planteamiento biológico y objetivo.
  2. Creación del conjunto de datos en R.
  3. Análisis exploratorio de los datos.
  4. Verificación de supuestos de normalidad y homogeneidad de varianzas.
  5. Selección y ejecución de la prueba estadística adecuada.
  6. Cálculo de intervalos de confianza al 95 %.
  7. Visualización de los resultados con gráficos de calidad de publicación.

1. Preparación del entorno de trabajo en R

Antes de iniciar las prácticas, se cargan los paquetes necesarios.
Si alguno no está instalado, descomente la línea install.packages() correspondiente.

# install.packages("dplyr")
# install.packages("ggplot2")
# install.packages("ggpubr")
# install.packages("dlookr")
# install.packages("car")
# install.packages("multcomp")
# install.packages("ggsignif")

library(dplyr)     # manipulación de datos
library(ggplot2)   # gráficos base
library(ggpubr)    # gráficos estadísticos y anotaciones
library(dlookr)    # exploración de normalidad y diagnóstico
library(car)       # prueba de Levene
library(multcomp)  # comparaciones post-hoc (Tukey, etc.)
library(ggsignif)  # anotaciones de significancia en gráficos

2. Práctica 1

Efecto de Metformina en la formación de complejos replicativos de ZIKV

2.1. Contexto biológico y objetivo

En esta práctica se analiza el efecto del tratamiento con Metformina (9 mM) frente a vehículo (0 mM) sobre la formación de complejos replicativos durante la infección por ZIKV (virus del Zika).

Se realizaron ensayos de inmunofluorescencia y microscopía confocal marcando dos proteínas virales:

  • Proteína E (envoltura) – señal en canal verde.
  • Proteína NS4A – señal en canal rojo.

Los núcleos se marcaron con DAPI (azul). A partir de estas imágenes se cuantificó el índice de colocalización de Pearson (PearsonCC) entre las señales de E y NS4A, utilizando el software ZEN Black (Carl Zeiss).

Se analizaron en total 60 células:

  • 30 células tratadas con vehículo
  • 30 células tratadas con metformina

El objetivo estadístico de la práctica es:

Evaluar si el tratamiento con metformina modifica significativamente la colocalización entre E y NS4A (índice de Pearson), en comparación con el vehículo.


2.2. Creación del conjunto de datos en R

Actividad 1 (obligatoria):
Reproduzca en R el conjunto de datos de la Tabla de índices de correlación de Pearson.

2.2.1. Vectores con datos de cada grupo

# Valores de PearsonCC para vehículo (30 observaciones)
pearson_vehicle <- c(
  0.69, 0.67, 0.81, 0.78, 0.68, 0.80, 0.91, 0.88, 0.88, 0.79,
  0.76, 0.64, 0.84, 0.79, 0.74, 0.92, 0.74, 0.71, 0.87, 0.64,
  0.84, 0.79, 0.74, 0.92, 0.74, 0.71, 0.87, 0.79, 0.80, 0.78
)

length(pearson_vehicle)  # debe ser 30
## [1] 30
# Valores de PearsonCC para metformina (30 observaciones)
pearson_metformin <- c(
  0.16, 0.21, 0.31, 0.47, 0.68, 0.69, 0.37, 0.48, 0.33, 0.54,
  0.43, 0.25, 0.48, 0.35, 0.43, 0.59, 0.23, 0.37, 0.20, 0.59,
  0.36, 0.27, 0.24, 0.48, 0.46, 0.09, 0.57, 0.50, 0.28, 0.39
)

length(pearson_metformin)  # debe ser 30
## [1] 30

2.2.2. Construcción del data frame

mett <- data.frame(
  Treatment = factor(
    c(rep("vehicle", length(pearson_vehicle)),
      rep("metformin", length(pearson_metformin))),
    levels = c("vehicle", "metformin")
  ),
  PearsonCC = c(pearson_vehicle, pearson_metformin)
)

str(mett)
## 'data.frame':    60 obs. of  2 variables:
##  $ Treatment: Factor w/ 2 levels "vehicle","metformin": 1 1 1 1 1 1 1 1 1 1 ...
##  $ PearsonCC: num  0.69 0.67 0.81 0.78 0.68 0.8 0.91 0.88 0.88 0.79 ...
head(mett)
##   Treatment PearsonCC
## 1   vehicle      0.69
## 2   vehicle      0.67
## 3   vehicle      0.81
## 4   vehicle      0.78
## 5   vehicle      0.68
## 6   vehicle      0.80
nrow(mett)   # debe ser 60
## [1] 60

2.3. Análisis exploratorio descriptivo

Actividad 2:
Describa la distribución de PearsonCC por grupo, incluyendo:

  • Tamaño de muestra.
  • Media.
  • Desviación estándar.
  • Intervalos de confianza al 95 %.

2.3.1. Funciones auxiliares para intervalos de confianza

lower_ci <- function(mean, se, n, conf_level = 0.95) {
  mean - qt(1 - (1 - conf_level) / 2, df = n - 1) * se
}

upper_ci <- function(mean, se, n, conf_level = 0.95) {
  mean + qt(1 - (1 - conf_level) / 2, df = n - 1) * se
}

2.3.2. Resumen por tratamiento

desc_mett <- mett %>%
  group_by(Treatment) %>%
  summarise(
    n    = n(),
    mean = mean(PearsonCC, na.rm = TRUE),
    sd   = sd(PearsonCC, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(
    se       = sd / sqrt(n),
    lower_ci = lower_ci(mean, se, n),
    upper_ci = upper_ci(mean, se, n)
  )

desc_mett
## # A tibble: 2 × 7
##   Treatment     n  mean     sd     se lower_ci upper_ci
##   <fct>     <int> <dbl>  <dbl>  <dbl>    <dbl>    <dbl>
## 1 vehicle      30 0.784 0.0803 0.0147    0.754    0.814
## 2 metformin    30 0.393 0.153  0.0279    0.336    0.450

2.4. Verificación de supuestos para la prueba t

2.4.1. Supuesto de normalidad (Shapiro–Wilk)

with(mett, shapiro.test(PearsonCC[Treatment == "vehicle"]))
## 
##  Shapiro-Wilk normality test
## 
## data:  PearsonCC[Treatment == "vehicle"]
## W = 0.96534, p-value = 0.4207
with(mett, shapiro.test(PearsonCC[Treatment == "metformin"]))
## 
##  Shapiro-Wilk normality test
## 
## data:  PearsonCC[Treatment == "metformin"]
## W = 0.98343, p-value = 0.9075

2.4.2. Evaluación gráfica de normalidad

mett %>%
  group_by(Treatment) %>%
  plot_normality(PearsonCC)


2.4.3. Supuesto de homogeneidad de varianzas

Se aplica la prueba F para igualdad de varianzas.

res_ftest <- var.test(PearsonCC ~ Treatment, data = mett)
res_ftest
## 
##  F test to compare two variances
## 
## data:  PearsonCC by Treatment
## F = 0.2758, num df = 29, denom df = 29, p-value = 0.0008667
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  0.1312703 0.5794512
## sample estimates:
## ratio of variances 
##          0.2757984
  • Si p < 0.05 → varianzas desiguales → usar t de Welch (var.equal = FALSE).
  • Si p ≥ 0.05 → varianzas similares → se puede usar t clásica (var.equal = TRUE).

2.5. Prueba estadística: t de Student para dos muestras independientes

Actividad 3:
Seleccione la prueba apropiada con base en los supuestos y ejecútela en R.

# Ajustar var.equal según el resultado de la prueba F
res_t_mett <- t.test(
  PearsonCC ~ Treatment,
  data       = mett,
  alternative = "two.sided",
  var.equal   = FALSE   # modifique a TRUE si las varianzas son homogéneas
)

res_t_mett
## 
##  Welch Two Sample t-test
## 
## data:  PearsonCC by Treatment
## t = 12.385, df = 43.866, p-value = 6.455e-16
## alternative hypothesis: true difference in means between group vehicle and group metformin is not equal to 0
## 95 percent confidence interval:
##  0.3270915 0.4542418
## sample estimates:
##   mean in group vehicle mean in group metformin 
##               0.7840000               0.3933333

Extracto de elementos clave:

p_value_t <- res_t_mett$p.value
means_t   <- res_t_mett$estimate
ci_t      <- res_t_mett$conf.int

p_value_t
## [1] 6.455027e-16
means_t
##   mean in group vehicle mean in group metformin 
##               0.7840000               0.3933333
ci_t
## [1] 0.3270915 0.4542418
## attr(,"conf.level")
## [1] 0.95

2.6. Visualización de resultados

2.6.1. Boxplot con puntos individuales y p-valor

max_y_mett <- max(mett$PearsonCC, na.rm = TRUE)

boxplot_mett <- ggboxplot(
  mett,
  x      = "Treatment",
  y      = "PearsonCC",
  color  = "Treatment",
  palette = c("#00AFBB", "#E7B800"),
  ylab   = "Índice de colocalización de Pearson (E vs NS4A)",
  xlab   = "Tratamiento",
  add    = "jitter"
)

boxplot_mett +
  stat_compare_means(
    method  = "t.test",
    label.y = max_y_mett * 1.05
  ) +
  stat_compare_means(
    aes(label = ..p.signif..),
    method  = "t.test",
    label.y = max_y_mett * 1.10
  )


2.6.2. Barplot con medias y desviación estándar

barplot_mett <- ggbarplot(
  mett,
  x       = "Treatment",
  y       = "PearsonCC",
  color   = "Treatment",
  fill    = "Treatment",          # usar la variable de grupo como relleno
  palette = c("#00AFBB", "#E7B800"),
  ylab    = "Índice de colocalización de Pearson (E vs NS4A)",
  xlab    = "Tratamiento",
  add     = "mean_sd"             # barras de error con media ± SD
)

barplot_mett +
  stat_compare_means(
    method  = "t.test",
    label.y = max_y_mett * 1.05
  ) +
  stat_compare_means(
    aes(label = ..p.signif..),
    method  = "t.test",
    label.y = max_y_mett * 1.10
  )


2.7. Síntesis de la práctica 1

Al finalizar, el alumnado deberá ser capaz de:

  • Construir un data.frame en R a partir de datos experimentales.
  • Explorar descriptivamente los datos por grupo.
  • Evaluar normalidad y homogeneidad de varianzas.
  • Aplicar correctamente una prueba t para dos muestras independientes.
  • Reportar p-valor, medias, desviaciones estándar e intervalos de confianza.
  • Comunicar resultados con gráficos adecuados.

3. Práctica 2

Análisis de expresión relativa de NUP98 en tres condiciones experimentales

3.1. Contexto biológico y objetivo

En esta práctica se analizan valores de intensidad relativa de señal (RBI) para la proteína NUP98 en tres condiciones experimentales:

  • Zika24h

  • NS2B3Mut

  • NS2B3WT

Cada condición tiene tres replicados. El objetivo es:

Determinar si existen diferencias estadísticamente significativas en la intensidad relativa de NUP98 entre las tres condiciones.


3.2. Creación del data frame en R

Actividad 4:
Construya un data.frame en R con los datos proporcionados.

3.2.1. Datos de la práctica

  • Zika24h: 0.547, 0.52, 0.65
  • NS2B3Mut: 0.988, 1.09, 0.927
  • NS2B3WT: 0.72, 0.739, 0.82
nup98 <- data.frame(
  nup98 = factor(
    c(rep("Zika24h", 3),
      rep("NS2B3Mut", 3),
      rep("NS2B3WT", 3)),
    levels  = c("Zika24h", "NS2B3Mut", "NS2B3WT"),
    ordered = TRUE
  ),
  RBI = c(
    0.547, 0.52, 0.65,
    0.988, 1.09, 0.927,
    0.72, 0.739, 0.82
  )
)

str(nup98)
## 'data.frame':    9 obs. of  2 variables:
##  $ nup98: Ord.factor w/ 3 levels "Zika24h"<"NS2B3Mut"<..: 1 1 1 2 2 2 3 3 3
##  $ RBI  : num  0.547 0.52 0.65 0.988 1.09 0.927 0.72 0.739 0.82
nup98
##      nup98   RBI
## 1  Zika24h 0.547
## 2  Zika24h 0.520
## 3  Zika24h 0.650
## 4 NS2B3Mut 0.988
## 5 NS2B3Mut 1.090
## 6 NS2B3Mut 0.927
## 7  NS2B3WT 0.720
## 8  NS2B3WT 0.739
## 9  NS2B3WT 0.820

3.3. Análisis exploratorio descriptivo

desc_nup98 <- nup98 %>%
  group_by(nup98) %>%
  summarise(
    n    = n(),
    mean = mean(RBI, na.rm = TRUE),
    sd   = sd(RBI, na.rm = TRUE),
    .groups = "drop"
  )

desc_nup98
## # A tibble: 3 × 4
##   nup98        n  mean     sd
##   <ord>    <int> <dbl>  <dbl>
## 1 Zika24h      3 0.572 0.0686
## 2 NS2B3Mut     3 1.00  0.0824
## 3 NS2B3WT      3 0.760 0.0531

3.4. Verificación de supuestos para ANOVA

3.4.1. Ajuste inicial del modelo ANOVA

resultado_anova <- aov(RBI ~ nup98, data = nup98)
summary(resultado_anova)
##             Df  Sum Sq Mean Sq F value   Pr(>F)    
## nup98        2 0.27798 0.13899   29.14 0.000813 ***
## Residuals    6 0.02862 0.00477                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

3.4.2. Homogeneidad de varianzas

a) Evaluación gráfica (residuos vs valores ajustados)

plot(resultado_anova, which = 1)

b) Prueba de Levene

leveneTest(RBI ~ nup98, data = nup98)
## Levene's Test for Homogeneity of Variance (center = median)
##       Df F value Pr(>F)
## group  2  0.1364 0.8751
##        6

3.4.3. Normalidad de los residuos

resid_anova <- residuals(resultado_anova)

# Q-Q plot
plot(resultado_anova, which = 2)

# Prueba de Shapiro–Wilk sobre los residuos
shapiro.test(resid_anova)
## 
##  Shapiro-Wilk normality test
## 
## data:  resid_anova
## W = 0.88378, p-value = 0.172

3.5. Prueba ANOVA de una vía y comparaciones post-hoc

3.5.1. ANOVA global

summary(resultado_anova)
##             Df  Sum Sq Mean Sq F value   Pr(>F)    
## nup98        2 0.27798 0.13899   29.14 0.000813 ***
## Residuals    6 0.02862 0.00477                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

3.5.2. Prueba de Tukey (post-hoc)

TukeyHSD(resultado_anova)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = RBI ~ nup98, data = nup98)
## 
## $nup98
##                        diff         lwr         upr     p adj
## NS2B3Mut-Zika24h  0.4293333  0.25631482  0.60235185 0.0006545
## NS2B3WT-Zika24h   0.1873333  0.01431482  0.36035185 0.0367107
## NS2B3WT-NS2B3Mut -0.2420000 -0.41501852 -0.06898148 0.0121671

Alternativa con multcomp:

summary(
  glht(
    resultado_anova,
    linfct = mcp(nup98 = "Tukey")
  )
)
## 
##   Simultaneous Tests for General Linear Hypotheses
## 
## Multiple Comparisons of Means: Tukey Contrasts
## 
## 
## Fit: aov(formula = RBI ~ nup98, data = nup98)
## 
## Linear Hypotheses:
##                         Estimate Std. Error t value Pr(>|t|)    
## NS2B3Mut - Zika24h == 0  0.42933    0.05639   7.614   <0.001 ***
## NS2B3WT - Zika24h == 0   0.18733    0.05639   3.322   0.0364 *  
## NS2B3WT - NS2B3Mut == 0 -0.24200    0.05639  -4.292   0.0126 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)

3.6. Visualización de resultados

3.6.1. Boxplot por grupo

max_y_nup <- max(nup98$RBI, na.rm = TRUE)

boxplot_nup <- ggboxplot(
  nup98,
  x      = "nup98",
  y      = "RBI",
  color  = "nup98",                         # color por grupo
  fill   = "nup98",                         # relleno por grupo
  palette = c("#00AFBB", "#E7B800", "#FC4E07"),
  order  = c("Zika24h", "NS2B3Mut", "NS2B3WT"),
  ylab   = "Intensidad relativa (unidades arbitrarias)",
  xlab   = "Condiciones",
  add    = "jitter"
)

boxplot_nup +
  stat_compare_means(
    method  = "anova",
    label.y = max_y_nup * 1.05
  )


3.6.2. Anotaciones de comparaciones específicas

Definimos primero las comparaciones de interés:

my_comparisons <- list(
  c("Zika24h",  "NS2B3Mut"),
  c("Zika24h",  "NS2B3WT"),
  c("NS2B3Mut", "NS2B3WT")
)

Y aplicamos anotaciones con ggsignif:

 ggplot(nup98, aes(x = nup98, y = RBI)) +
  geom_boxplot() +
  geom_signif(
    comparisons      = my_comparisons,
    map_signif_level = TRUE,
    step_increase    = 0.1
  ) +
  ylab("Intensidad relativa (unidades arbitrarias)") +
  xlab("Condiciones")


3.6.3. Barplot con medias y desviación estándar

barplot_nup <- ggbarplot(
  nup98,
  x       = "nup98",
  y       = "RBI",
  color   = "nup98",                         # contorno por grupo
  fill    = "nup98",                         # relleno por grupo
  palette = c("#00AFBB", "#E7B800", "#FC4E07"),
  order   = c("Zika24h", "NS2B3Mut", "NS2B3WT"),
  ylab    = "Intensidad relativa (unidades arbitrarias)",
  xlab    = "Condiciones",
  add     = "mean_sd"
)

max_y_nup <- max(nup98$RBI, na.rm = TRUE)

barplot_nup +
  stat_compare_means(
    method  = "anova",
    label.y = max_y_nup * 1.05
  )


3.6.4. Gráfico de líneas de medias

 ggline(
  nup98,
  x     = "nup98",
  y     = "RBI",
  add   = c("mean_sd", "jitter"),
  order = c("Zika24h", "NS2B3Mut", "NS2B3WT"),
  ylab  = "Intensidad relativa (unidades arbitrarias)",
  xlab  = "Condiciones"
)


4. Entregables sugeridos para el curso

Para cada práctica, se recomienda que el alumnado entregue:

  1. El script en R (o el archivo .Rmd) con:
    • Código comentado.
    • Resultados principales (tablas y gráficos).
  2. Un breve informe interpretativo (1–2 cuartillas) que responda:
    • ¿Cuál es la pregunta biológica?
    • ¿Qué prueba estadística se aplicó y por qué?
    • ¿Cuáles son los resultados (medias, p-valores, IC 95 %)?
    • ¿Cuál es la interpretación biológica de los hallazgos?

De esta forma, el curso se construye simultáneamente en tres niveles: