Actividad 1

library(ggplot2)
library(readr)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.1     ✔ stringr   1.5.2
## ✔ lubridate 1.9.4     ✔ tibble    3.3.0
## ✔ purrr     1.1.0     ✔ tidyr     1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
datos <- read_csv("lipid_profile_dataset.csv", show_col_types = FALSE)


names(datos) <- c("Patient_ID", "id", "calidad_fisica", "calidad_mental", "corticoides", 
                  "HDL_Cholesterol_mg_dl", "LDL_Cholesterol_mg_dl", "Triglycerides_mg_dl", 
                  "Triglycerides_mg_dl")

names(datos)
## [1] "Patient_ID"            "id"                    "calidad_fisica"       
## [4] "calidad_mental"        "corticoides"           "HDL_Cholesterol_mg_dl"
## [7] "LDL_Cholesterol_mg_dl" "Triglycerides_mg_dl"   "Triglycerides_mg_dl"
datos <- datos[ , !duplicated(names(datos))]

Histograma - Triglicéridos

ggplot(datos, aes(x = Triglycerides_mg_dl)) +
  geom_histogram(
    bins = 30,
    fill = "#4682B4",
    color = "white",
    alpha = 0.8
  ) +
  labs(
    title = "Distribución de Triglicéridos",
    subtitle = "Frecuencia de valores en la muestra experimental",
    x = "Triglicéridos (mg/dL)",
    y = "Frecuencia",
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", color = "#003366", size = 18, hjust = 0.5),
    plot.subtitle = element_text(face = "italic", color = "#4682f4", size = 13, hjust = 0.5),
    plot.caption = element_text(color = "gray40", size = 10, hjust = 1),
    axis.title.x = element_text(face = "bold", color = "#003366", size = 13),
    axis.title.y = element_text(face = "bold", color = "#003366", size = 13),
    axis.text = element_text(size = 11, color = "gray20"),
    panel.grid.minor = element_blank()
  )

ggsave("histograma_trigliceridos.png", width = 8, height = 6, dpi = 300)

Histograma - Colesterol HDL

ggplot(datos, aes(x = HDL_Cholesterol_mg_dl)) +
  geom_histogram(
    bins = 30,
    fill = "#4682B4",
    color = "white",
    alpha = 0.8
  ) +
  labs(
    title = "Distribución de Colesterol HDL",
    subtitle = "Frecuencia de valores en la muestra experimental",
    x = "Colesterol HDL (mg/dL)",
    y = "Frecuencia",
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", color = "#003366", size = 18, hjust = 0.5),
    plot.subtitle = element_text(face = "italic", color = "#4682f4", size = 13, hjust = 0.5),
    plot.caption = element_text(color = "gray40", size = 10, hjust = 1),
    axis.title.x = element_text(face = "bold", color = "#003366", size = 13),
    axis.title.y = element_text(face = "bold", color = "#003366", size = 13),
    axis.text = element_text(size = 11, color = "gray20"),
    panel.grid.minor = element_blank()
  )

ggsave("histograma_hdl.png", width = 8, height = 6, dpi = 300)

Histograma - Colesterol LDL

ggplot(datos, aes(x = LDL_Cholesterol_mg_dl)) +
  geom_histogram(
    bins = 30,
    fill = "#4682B4",
    color = "white",
    alpha = 0.8
  ) +
  labs(
    title = "Distribución de Colesterol LDL",
    subtitle = "Frecuencia de valores en la muestra experimental",
    x = "Colesterol LDL (mg/dL)",
    y = "Frecuencia",
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", color = "#003366", size = 18, hjust = 0.5),
    plot.subtitle = element_text(face = "italic", color = "#4682f4", size = 13, hjust = 0.5),
    plot.caption = element_text(color = "gray40", size = 10, hjust = 1),
    axis.title.x = element_text(face = "bold", color = "#003366", size = 13),
    axis.title.y = element_text(face = "bold", color = "#003366", size = 13),
    axis.text = element_text(size = 11, color = "gray20"),
    panel.grid.minor = element_blank()
  )

ggsave("histograma_ldl.png", width = 8, height = 6, dpi = 300)

Estadística

blue_cols <- list(
  light_blue = "#87CEFA",
  medium_blue = "#4682B4",
  dark_blue = "#003366",
  steel_blue = "#4682B4",
  gray90 = "gray90"
)

summary_stats <- datos %>%
  reframe(
    # Triglicéridos
    Triglycerides_mean   = mean(Triglycerides_mg_dl, na.rm = TRUE),
    Triglycerides_median = median(Triglycerides_mg_dl),
    Triglycerides_sd     = sd(Triglycerides_mg_dl, na.rm = TRUE),
    Triglycerides_range  = range(Triglycerides_mg_dl, na.rm = TRUE),
    
    # HDL
    HDL_mean     = mean(HDL_Cholesterol_mg_dl, na.rm = TRUE),
    HDL_median   = median(HDL_Cholesterol_mg_dl, na.rm = TRUE),
    HDL_sd       = sd(HDL_Cholesterol_mg_dl, na.rm = TRUE),
    HDL_range    = range(HDL_Cholesterol_mg_dl, na.rm = TRUE),
    
    # LDL
    LDL_mean     = mean(LDL_Cholesterol_mg_dl, na.rm = TRUE),
    LDL_median   = median(LDL_Cholesterol_mg_dl, na.rm = TRUE),
    LDL_sd       = sd(LDL_Cholesterol_mg_dl, na.rm = TRUE),
    LDL_range    = range(LDL_Cholesterol_mg_dl, na.rm = TRUE)
  )

summary_stats %>%
  pivot_longer(cols = everything(), names_to = "Metric", values_to = "Value") %>%
  knitr::kable(
    caption = "Estadísticas descriptivas de los perfiles lipídicos",
    align = "l"
  ) %>%
  kableExtra::kable_styling(
    full_width = FALSE, bootstrap_options = c("striped", "condensed"),
    font_size = 13
  ) %>%
  kableExtra::row_spec(0, bold = TRUE, color = "white", background = blue_cols$dark_blue) %>%
  kableExtra::column_spec(1, color = blue_cols$dark_blue) %>%
  kableExtra::add_footnote(label = "Las estadísticas de rango muestran el valor mínimo y máximo.")
Estadísticas descriptivas de los perfiles lipídicos
Metric Value
Triglycerides_mean 195.789922
Triglycerides_median 193.098465
Triglycerides_sd 33.483998
Triglycerides_range 124.000000
HDL_mean 50.125998
HDL_median 52.483342
HDL_sd 9.845257
HDL_range 23.166105
LDL_mean 51.495000
LDL_median 52.000000
LDL_sd 15.980970
LDL_range 22.000000
Triglycerides_mean 195.789922
Triglycerides_median 193.098465
Triglycerides_sd 33.483998
Triglycerides_range 315.000000
HDL_mean 50.125998
HDL_median 52.483342
HDL_sd 9.845257
HDL_range 66.757889
LDL_mean 51.495000
LDL_median 52.000000
LDL_sd 15.980970
LDL_range 108.000000
a Las estadísticas de rango muestran el valor mínimo y máximo.

Discusión de resultados

Los histogramas muestran la distribución de los tres parámetros lipídicos: triglicéridos, colesterol HDL y colesterol LDL. Para los triglicéridos, la distribución es asimétrica, con un pico en valores de 200 mg/dL, lo que indica que la mayoría de los pacientes tienen niveles dentro del rango normal. Sin embargo, se observa una cola hacia la derecha, lo que sugiere que un pequeño grupo de pacientes tiene niveles elevados de triglicéridos (>250 mg/dL), lo que puede estar asociado con un mayor riesgo cardiovascular. En cuanto al colesterol HDL, el histograma muestra una distribución bimodal, con un pico en valores bajos (alrededor de 40 mg/dL) y otro en valores cercanos a 60 mg/dL, lo que sugiere que existen dos grupos de pacientes: uno con HDL bajo (lo que podría aumentar el riesgo cardiovascular) y otro con HDL dentro de los rangos saludables. Los valores atípicos en la cola inferior (<30 mg/dL) reflejan pacientes con niveles muy bajos de HDL, lo que indica una mayor susceptibilidad a enfermedades del corazón. Finalmente, el colesterol LDL presenta una distribución más homogénea, con la mayoría de los pacientes con niveles alrededor de 60 mg/dL, aunque se observa una cola hacia valores más altos, lo que sugiere que algunos pacientes tienen niveles elevados de LDL, lo que también aumenta el riesgo de aterosclerosis y otros problemas cardiovasculares. Comparando la variabilidad, los triglicéridos muestran la mayor dispersión en los valores, lo que indica una gran heterogeneidad entre los pacientes, mientras que el HDL es el parámetro con menor variabilidad, lo que podría indicar que la mayoría de los pacientes tienen valores similares de HDL. El LDL, por su parte, presenta moderada dispersión. Por lo tanto, los tres parámetros muestran patrones de variabilidad en la población, sugiriendo que mientras algunos pacientes presentan un perfil lipídico saludable, otros están en riesgo elevado de enfermedades cardiovasculares debido a los valores elevados de triglicéridos o LDL y los niveles bajos de HDL.

Actividad 2

Volcano Plot

library(tidyverse)
library(ggrepel)

datos <- read.csv("gene_expression_inflam.csv", header = TRUE, sep = ",")

eps <- 1e-12

str(datos)
## 'data.frame':    100 obs. of  52 variables:
##  $ Patient_ID : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Group      : chr  "Healthy" "Healthy" "Healthy" "LungCancer" ...
##  $ EX_IL1B    : num  7.44 7.18 9.18 10.01 11.49 ...
##  $ EX_IL6     : num  6.25 8.59 6.97 11.49 9.99 ...
##  $ EX_TNF     : num  9.38 6.73 9.2 12.86 12.09 ...
##  $ EX_CXCL8   : num  7.16 8.3 7.51 10.69 12.62 ...
##  $ EX_CCL2    : num  6.03 9.25 8.08 11.95 12.68 ...
##  $ EX_NFKB1   : num  7.85 9.22 9.16 11.85 10.03 ...
##  $ EX_RELA    : num  8.74 9.12 6.08 8.73 11.48 ...
##  $ EX_PTGS2   : num  7.61 6.71 7.72 13.02 12.57 ...
##  $ EX_TLR4    : num  8.45 6.74 7.93 12.93 10.58 ...
##  $ EX_IFNG    : num  7.74 7.9 9.3 12.81 10.09 ...
##  $ EX_STAT3   : num  7.05 8.7 8.76 10.53 10.79 ...
##  $ EX_ICAM1   : num  7.82 7.11 9.45 11.01 10.49 ...
##  $ EX_VCAM1   : num  9.32 7.64 8.22 11.98 10.78 ...
##  $ EX_CXCL10  : num  9.15 7.98 8.5 11.99 11.47 ...
##  $ EX_TLR2    : num  7.66 5.59 7.26 8.66 10.45 ...
##  $ EX_TLR9    : num  7.09 7.61 8.47 11 11.12 ...
##  $ EX_NLRP3   : num  7.38 7.24 7.72 8.85 11.32 ...
##  $ EX_CASP1   : num  8.98 7.97 7.9 10.55 10.24 ...
##  $ EX_GSDMD   : num  7.94 7.94 8.54 10.27 11.62 ...
##  $ EX_PYCARD  : num  7.38 8.57 9.89 10.74 11.11 ...
##  $ EX_TP53    : num  7.49 8.06 6.38 5.62 7.34 ...
##  $ EX_BAX     : num  7.55 8.96 8.86 6.86 5.97 ...
##  $ EX_BID     : num  8.29 8.51 7.66 7.62 7.36 ...
##  $ EX_BAD     : num  8.88 6.65 7.62 4.59 7.2 ...
##  $ EX_BAK1    : num  10.79 7.69 8.86 5.8 6.87 ...
##  $ EX_CASP3   : num  8.84 7.68 8.35 6.69 5.83 ...
##  $ EX_CASP7   : num  6.14 8.33 8.52 7.44 6.73 ...
##  $ EX_CASP8   : num  8.51 9.38 7.95 6.46 5.68 ...
##  $ EX_CASP9   : num  6.71 8.33 8.16 7.31 6.44 ...
##  $ EX_APAF1   : num  7.31 7.66 6.71 8.05 3.87 ...
##  $ EX_FAS     : num  9.19 10.47 8.11 5.96 8.18 ...
##  $ EX_FADD    : num  6.87 8.64 7.9 6.54 5.89 ...
##  $ EX_PMAIP1  : num  6.75 6.41 9.22 7.52 7.69 ...
##  $ EX_DIABLO  : num  7.41 8.45 7.23 7.26 8.73 ...
##  $ EX_PARP1   : num  6.1 7.31 7.38 6.16 7.33 ...
##  $ EX_BCL2    : num  8.64 11.41 9.7 8.97 12.74 ...
##  $ EX_MCL1    : num  8.16 7.42 7.96 10.11 11.02 ...
##  $ EX_XIAP    : num  8.04 10.15 5.85 12.99 11.81 ...
##  $ EX_CFLAR   : num  9.68 6.87 9.09 10.12 10.06 ...
##  $ EX_TNFSF10 : num  7.16 7.98 8.01 10.74 10.82 ...
##  $ EX_MLKL    : num  8.68 7.33 8.36 10.19 9.56 ...
##  $ EX_RIPK1   : num  8.24 8.81 8.44 9.69 11.41 ...
##  $ EX_RIPK3   : num  8.81 6.48 7.68 11.84 11.27 ...
##  $ EX_TNFRSF1A: num  8.83 8.17 6.3 10.31 11.15 ...
##  $ EX_HMGB1   : num  10.47 7.1 10.17 8.87 11.01 ...
##  $ EX_HSP90AA1: num  8.23 8.94 6.9 8.15 11.36 ...
##  $ EX_HSPB1   : num  9.62 9.12 6.06 10.82 8.97 ...
##  $ EX_S100A8  : num  10.26 6.7 7.8 11.06 8.21 ...
##  $ EX_S100A9  : num  7.26 5.41 8.99 10.42 11.79 ...
##  $ EX_ALDH1A1 : num  6.88 8.42 9.98 11.61 10.8 ...
colnames(datos)
##  [1] "Patient_ID"  "Group"       "EX_IL1B"     "EX_IL6"      "EX_TNF"     
##  [6] "EX_CXCL8"    "EX_CCL2"     "EX_NFKB1"    "EX_RELA"     "EX_PTGS2"   
## [11] "EX_TLR4"     "EX_IFNG"     "EX_STAT3"    "EX_ICAM1"    "EX_VCAM1"   
## [16] "EX_CXCL10"   "EX_TLR2"     "EX_TLR9"     "EX_NLRP3"    "EX_CASP1"   
## [21] "EX_GSDMD"    "EX_PYCARD"   "EX_TP53"     "EX_BAX"      "EX_BID"     
## [26] "EX_BAD"      "EX_BAK1"     "EX_CASP3"    "EX_CASP7"    "EX_CASP8"   
## [31] "EX_CASP9"    "EX_APAF1"    "EX_FAS"      "EX_FADD"     "EX_PMAIP1"  
## [36] "EX_DIABLO"   "EX_PARP1"    "EX_BCL2"     "EX_MCL1"     "EX_XIAP"    
## [41] "EX_CFLAR"    "EX_TNFSF10"  "EX_MLKL"     "EX_RIPK1"    "EX_RIPK3"   
## [46] "EX_TNFRSF1A" "EX_HMGB1"    "EX_HSP90AA1" "EX_HSPB1"    "EX_S100A8"  
## [51] "EX_S100A9"   "EX_ALDH1A1"
gene_cols <- names(datos)[grepl("^EX_", names(datos))]

de <- map_dfr(gene_cols, function(gene) {
  grupo_A <- datos %>% filter(Group == "Healthy") %>% pull(gene)
  grupo_B <- datos %>% filter(Group == "LungCancer") %>% pull(gene)
  
  t_res <- tryCatch(t.test(grupo_B, grupo_A), error = function(e) NULL)
  p_val <- if (!is.null(t_res)) t_res$p.value else NA_real_
  
  log2FC <- log2((mean(grupo_B, na.rm = TRUE) + eps) /
                 (mean(grupo_A, na.rm = TRUE) + eps))
  
  tibble(Gene = gene, log2FoldChange = log2FC, pvalue = p_val)
})

de <- de %>% mutate(padj = p.adjust(pvalue, method = "BH"))

de <- de %>%
  mutate(
    Significativo = ifelse(padj < 0.05 & abs(log2FoldChange) > 1, "Sí", "No")
  )

ggplot(de, aes(x = log2FoldChange, y = -log10(padj), color = Significativo)) +
  geom_point(alpha = 0.9, size = 2) +
  geom_vline(xintercept = c(-1, 1), color = "#003366", linetype = "dashed") +  # Líneas guías en ±1
  geom_hline(yintercept = -log10(0.05), color = "#003366", linetype = "dashed") +  # Línea horizontal en p = 0.05
  scale_color_manual(values = c("Sí" = "red", "No" = "#4682B4")) +  # Resaltar genes significativos en rojo
  geom_text_repel(
    data = de %>% filter(Significativo == "Sí"),
    aes(label = Gene),
    size = 3, max.overlaps = 10, seed = 123
  ) +
  theme_minimal(base_size = 13) +
  labs(
    title = "Volcano Plot — Expresión Génica (Healthy vs LungCancer)",
    subtitle = "Genes significativos (p < 0.05 y |log₂FC| > 1)",
    x = expression(log[2]("Fold Change")),
    y = expression(-log[10]("p-valor ajustado")),
    color = "Significativo"
  ) +
  theme(
    plot.title = element_text(face = "bold", color = "#003366", hjust = 0.5, size = 15),
    plot.subtitle = element_text(color = "#4682B4", hjust = 0.5, size = 12),
    legend.position = "top",
    panel.grid.minor = element_blank(),
    axis.title = element_text(color = "#283593")
  )

ggsave("volcano_plot.png", width = 8, height = 6, dpi = 300)

Discusión de resultados

En el volcano plot no se observan genes sobreexpresados en el grupo con cáncer de pulmón ni genes subexpresados en el grupo sano, ya que no hay puntos rojos que representen genes con |log₂FC| > 1 y p < 0.05. Los puntos en el gráfico están principalmente dentro de la zona no significativa, es decir, dentro de las líneas punteadas que marcan los umbrales de corte. Esto sugiere que no hay diferencias importantes en la expresión génica entre los dos grupos para los genes seleccionados. Aunque los valores de log₂FC y p-valor ajustado están por debajo de los umbrales establecidos, lo que podría indicar que los genes en este análisis no están vinculados a diferencias biológicas significativas entre Healthy y LungCancer, esto no significa que no existan genes relevantes en otros contextos o que no se puedan observar diferencias en futuras investigaciones con más genes o muestras. En términos de procesos biológicos, la falta de genes significativamente expresados en este análisis puede indicar que no hay un patrón claro relacionado con inflamación, apoptosis o necrosis en este conjunto de datos, lo que resalta la importancia de ampliar el análisis para capturar otros genes potencialmente involucrados en la progresión del cáncer de pulmón.

Heatmap

library(pheatmap)
library(reshape2)
## 
## Adjuntando el paquete: 'reshape2'
## The following object is masked from 'package:tidyr':
## 
##     smiths
library(dplyr)

datos <- read.csv("gene_expression_inflam.csv", header = TRUE, sep = ",")

genes_expresion <- grep("^EX_", names(datos), value = TRUE)

expr <- datos[, genes_expresion]

if ("Patient_ID" %in% names(datos)) {
  rownames(expr) <- paste0(datos$Patient_ID)
} else if ("id" %in% names(datos)) {
  rownames(expr) <- paste0(datos$id)
} else {
  rownames(expr) <- paste0(seq_len(nrow(expr)))
}

expr_mat <- as.matrix(expr)

expr_mat[!is.finite(expr_mat)] <- 0

filas_validas <- apply(expr_mat, 1, sd, na.rm = TRUE) != 0
expr_mat <- expr_mat[filas_validas, ]

expr_mat <- scale(expr_mat)

anotacion <- data.frame(Grupo = as.factor(datos$Group[filas_validas]))
rownames(anotacion) <- rownames(expr_mat)

ann_colors <- list(
  Grupo = c(
    Healthy = "#4682B4",
    LungCancer = "#003366"
  )
)

png("heatmap.png", width = 1000, height = 1500, res = 150)

pheatmap(
  expr_mat,
  annotation_row = anotacion,
  annotation_colors = ann_colors,
  color = colorRampPalette(c("#003366", "white", "#FFD700"))(100),
  cluster_rows = TRUE,
  cluster_cols = TRUE,
  fontsize = 6,
  fontsize_row = 7,
  fontsize_col = 7,
  main = "Mapa de Calor Jerárquico - Expresión Génica (Healthy vs LungCancer)",
  subtitle = "Expresión génica de pacientes clasificados por grupo",
  border_color = "gray80"
)

dev.off()
## png 
##   3

Discusión de resultados

En el heatmap se observa una separación clara entre los grupos Healthy y LungCancer, lo que está reflejado en los dendrogramas que agrupan a los pacientes de manera coherente. La mayoría de los pacientes con cáncer de pulmón se agrupan en un clúster separado, lo que indica que existen diferencias en la expresión génica entre ambos grupos. Los genes del grupo Healthy tienden a tener niveles más bajos de expresión (representados en tonos azules), mientras que en el grupo LungCancer, los genes muestran mayores niveles de expresión, especialmente en genes asociados con procesos como inflamación y proliferación celular. No se observan genes con sobreexpresión extrema, pero algunos genes, como los involucrados en la respuesta inmune, muestran niveles más altos de expresión en los pacientes con cáncer (en tonos amarillos), lo que sugiere su implicancia en mecanismos inflamatorios asociados con el cáncer. Además, se nota una mayor variabilidad en la expresión génica dentro del grupo LungCancer, lo que refleja la heterogeneidad tumoral en los pacientes. Por otro lado, el grupo Healthy muestra una expresión génica más homogénea, lo que podría reflejar un perfil biológico más estable. Estos patrones de expresión sugieren que los pacientes con LungCancer podrían tener una firma genética distinta, relacionada con procesos inflamatorios o de supervivencia celular, que los diferencia de los pacientes sanos.