Base de Mental Health Twitter

Introducción

El análisis discriminante lineal (LDA) es una técnica estadística multivariada que permite clasificar observaciones en grupos predefinidos a partir de un conjunto de variables cuantitativas. En el contexto de la salud mental y las redes sociales, esta técnica resulta especialmente útil para identificar patrones de comportamiento en usuarios de plataformas como X (antes Twitter) que permitan distinguir entre perfiles con indicios de depresión y perfiles sin ellos.

En este análisis se estudia una base de datos de usuarios de Twitter, donde la variable objetivo clasifica a cada usuario en dos grupos:

  • Con depresión
  • Sin depresión

El objetivo es determinar si las variables numéricas disponibles en la base permiten discriminar adecuadamente entre ambos grupos mediante un análisis discriminante lineal.

Carga de la base de datos en R

# knitr::opts_chunk$set(echo = TRUE)
library(readxl)

BD_Twitter <- read_excel("/Users/veronicapichardo/Desktop/AM/Bases examen/Mental-Health-Twitter.xlsx")

Se verifica que los datos se cargaron correctamente observando las primeras filas y la estructura de la base.

head(BD_Twitter)
str(BD_Twitter)
## tibble [20,000 × 7] (S3: tbl_df/tbl/data.frame)
##  $ ID        : num [1:20000] 0 1 2 3 4 5 6 7 8 9 ...
##  $ followers : num [1:20000] 84 84 84 84 84 84 84 84 84 84 ...
##  $ friends   : num [1:20000] 211 211 211 211 211 211 211 211 211 211 ...
##  $ favourites: num [1:20000] 251 251 251 251 251 251 251 251 251 251 ...
##  $ statuses  : num [1:20000] 837 837 837 837 837 837 837 837 837 837 ...
##  $ retweets  : num [1:20000] 0 1 0 2 1 1 1 0 0 41 ...
##  $ label     : chr [1:20000] "Con_depresion" "Con_depresion" "Con_depresion" "Con_depresion" ...
dim(BD_Twitter)
## [1] 20000     7
names(BD_Twitter)
## [1] "ID"         "followers"  "friends"    "favourites" "statuses"  
## [6] "retweets"   "label"

Preparación de la variable grupo

La variable que indica si el usuario presenta depresión o no es la variable de clasificación del análisis. Se convierte a factor y la base de datos se transforma a data.frame para garantizar compatibilidad con las funciones del análisis discriminante.

# Identificar la columna de clasificación — ajustar el nombre si es diferente
# En esta base la variable de grupo es "label" (0 = sin depresión, 1 = con depresión)
BD_Twitter$label <- as.factor(BD_Twitter$label)
BD_Twitter <- as.data.frame(BD_Twitter)
str(BD_Twitter)
## 'data.frame':    20000 obs. of  7 variables:
##  $ ID        : num  0 1 2 3 4 5 6 7 8 9 ...
##  $ followers : num  84 84 84 84 84 84 84 84 84 84 ...
##  $ friends   : num  211 211 211 211 211 211 211 211 211 211 ...
##  $ favourites: num  251 251 251 251 251 251 251 251 251 251 ...
##  $ statuses  : num  837 837 837 837 837 837 837 837 837 837 ...
##  $ retweets  : num  0 1 0 2 1 1 1 0 0 41 ...
##  $ label     : Factor w/ 2 levels "Con_depresion",..: 1 1 1 1 1 1 1 1 1 1 ...

Summary

summary(BD_Twitter)
##        ID          followers          friends          favourites   
##  Min.   :    0   Min.   :    0.0   Min.   :    0.0   Min.   :    0  
##  1st Qu.: 5000   1st Qu.:  177.0   1st Qu.:  211.0   1st Qu.:  243  
##  Median :10000   Median :  476.0   Median :  561.0   Median : 2752  
##  Mean   :10000   Mean   :  900.5   Mean   :  782.4   Mean   : 6398  
##  3rd Qu.:14999   3rd Qu.: 1197.0   3rd Qu.:  701.0   3rd Qu.: 8229  
##  Max.   :19999   Max.   :28614.0   Max.   :28514.0   Max.   :39008  
##     statuses          retweets                label      
##  Min.   :      3   Min.   :     0   Con_depresion:10000  
##  1st Qu.:   5129   1st Qu.:     0   Sin_depresion:10000  
##  Median :  13251   Median :     0                        
##  Mean   :  44394   Mean   :  1438                        
##  3rd Qu.:  52892   3rd Qu.:     1                        
##  Max.   :1063601   Max.   :839540

Interpretación: El resumen estadístico permite conocer cómo se comportan las variables de actividad de los 20,000 usuarios de Twitter analizados.

La base de datos está perfectamente balanceada:

\[ \text{Con depresión} = 10{,}000 \quad \text{usuarios} \]

\[ \text{Sin depresión} = 10{,}000 \quad \text{usuarios} \]

Esto significa que la mitad de los usuarios en la base presentan indicios de depresión, lo cual es importante porque garantiza que el modelo no esté sesgado hacia ningún grupo al momento de aprender a clasificar.

En cuanto a la variable followers (seguidores), el promedio es de aproximadamente 900 seguidores por usuario, pero el valor máximo llega a 28,614. Esta diferencia tan grande entre la media y el máximo indica que la mayoría de los usuarios tienen relativamente pocos seguidores, pero existe un grupo reducido de usuarios con una audiencia considerablemente mayor. Este tipo de distribución asimétrica es muy común en redes sociales.

La variable friends (cuentas seguidas) tiene un promedio de 782, con un máximo de 28,514. Esto muestra que el comportamiento de seguir cuentas también varía mucho entre usuarios: algunos siguen a miles de personas, mientras que la mayoría sigue a una cantidad moderada.

La variable favourites (publicaciones marcadas como favoritas) tiene un promedio de 6,398, pero puede llegar hasta 39,008. Esto indica que algunos usuarios interactúan de forma muy activa con el contenido de otros, mientras que muchos tienen una actividad más moderada en este aspecto.

La variable statuses (publicaciones realizadas) es la que presenta mayor variabilidad. Su media es de 44,394 publicaciones, pero el máximo asciende a 1,063,601. Esto revela que existe una minoría de usuarios extremadamente activos que han publicado cantidades masivas de contenido, mientras que la mayoría tiene una actividad mucho más moderada.

Por último, la variable retweets tiene una mediana de 0, lo que significa que la mitad de los usuarios no ha retuiteado contenido en absoluto. Sin embargo, el promedio de 1,438 y el máximo de 839,540 indican que unos pocos usuarios retuitean de forma muy intensa, elevando considerablemente el promedio.

En conjunto, el resumen muestra que la actividad en Twitter varía enormemente entre usuarios, con la presencia de valores muy extremos en casi todas las variables. Esta alta variabilidad puede ser útil para distinguir patrones entre usuarios con y sin depresión.

Análisis de la Suma Total de las Variables

# Seleccionar únicamente variables numéricas para el análisis
vars_numericas <- names(BD_Twitter)[sapply(BD_Twitter, is.numeric)]
vars_numericas
## [1] "ID"         "followers"  "friends"    "favourites" "statuses"  
## [6] "retweets"
colSums(BD_Twitter[, vars_numericas])
##         ID  followers    friends favourites   statuses   retweets 
##  199990000   18009679   15648575  127964711  887888392   28758546

Interpretación: La función colSums() permite obtener el total acumulado de cada variable considerando los 20,000 usuarios de la base de datos.

\[ n = 20{,}000 \text{ usuarios} \]

Los resultados obtenidos fueron:

\[ \sum \text{followers} = 18{,}009{,}679 \]

\[ \sum \text{friends} = 15{,}648{,}575 \]

\[ \sum \text{favourites} = 127{,}964{,}711 \]

\[ \sum \text{statuses} = 887{,}888{,}392 \]

\[ \sum \text{retweets} = 28{,}758{,}546 \]

Estos valores reflejan el volumen total de actividad acumulada en la base de datos. La variable statuses es la que concentra la mayor suma total, con casi 888 millones de publicaciones entre todos los usuarios. Esto confirma que publicar en Twitter es la forma de interacción más frecuente en esta comunidad.

Por su parte, favourites acumula más de 127 millones de marcas de favorito en total, lo que indica que los usuarios también consumen e interactúan activamente con el contenido de otros.

Los retweets acumulan casi 29 millones en total, una cifra menor en comparación con statuses y favourites, lo que sugiere que compartir publicaciones de otros es una actividad menos frecuente que publicar o dar favorito.

Es importante considerar que estas sumas son el resultado de sumar los datos de 20,000 usuarios, por lo que valores grandes simplemente reflejan la magnitud de la muestra analizada.

Resumen completo

resumen_completo_twitter <- function() {

  resumen_general <- summary(BD_Twitter)
  datos_numericos <- BD_Twitter[, sapply(BD_Twitter, is.numeric)]

  media       <- colMeans(datos_numericos, na.rm = TRUE)
  desviacion  <- apply(datos_numericos, 2, sd,  na.rm = TRUE)
  varianza    <- apply(datos_numericos, 2, var, na.rm = TRUE)

  estadisticos <- data.frame(
    Variable          = names(media),
    Media             = media,
    Desviacion_Estandar = desviacion,
    Varianza          = varianza,
    row.names         = NULL
  )

  return(list(
    Resumen      = resumen_general,
    Estadisticos = estadisticos
  ))
}

resultado_twitter <- resumen_completo_twitter()
resultado_twitter$Resumen
##        ID          followers          friends          favourites   
##  Min.   :    0   Min.   :    0.0   Min.   :    0.0   Min.   :    0  
##  1st Qu.: 5000   1st Qu.:  177.0   1st Qu.:  211.0   1st Qu.:  243  
##  Median :10000   Median :  476.0   Median :  561.0   Median : 2752  
##  Mean   :10000   Mean   :  900.5   Mean   :  782.4   Mean   : 6398  
##  3rd Qu.:14999   3rd Qu.: 1197.0   3rd Qu.:  701.0   3rd Qu.: 8229  
##  Max.   :19999   Max.   :28614.0   Max.   :28514.0   Max.   :39008  
##     statuses          retweets                label      
##  Min.   :      3   Min.   :     0   Con_depresion:10000  
##  1st Qu.:   5129   1st Qu.:     0   Sin_depresion:10000  
##  Median :  13251   Median :     0                        
##  Mean   :  44394   Mean   :  1438                        
##  3rd Qu.:  52892   3rd Qu.:     1                        
##  Max.   :1063601   Max.   :839540
resultado_twitter$Estadisticos

Interpretación:

El resumen estadístico detallado muestra la media, desviación estándar y varianza de cada variable numérica.

En cuanto a las medias, la variable statuses presenta el promedio más alto:

\[ \bar{x}_{\text{statuses}} = 44{,}394 \]

lo que indica que, en promedio, cada usuario ha realizado más de 44 mil publicaciones. Esto refleja que los usuarios de esta base son relativamente activos en la plataforma.

La variable retweets tiene una media de:

\[ \bar{x}_{\text{retweets}} = 1{,}438 \]

aunque su mediana es 0, lo que confirma que esta media está fuertemente influenciada por usuarios con comportamientos extremos.

Respecto a la variabilidad, statuses presenta la mayor varianza:

\[ s^2_{\text{statuses}} = 19{,}818{,}591{,}468 \]

lo que indica que la cantidad de publicaciones varía enormemente entre usuarios. Algunos publican miles o incluso millones de tweets, mientras que otros apenas han comenzado a usar la plataforma.

La variable retweets también muestra una varianza muy alta:

\[ s^2_{\text{retweets}} = 228{,}604{,}273 \]

lo cual confirma que el comportamiento de retuitear es muy heterogéneo: la mayoría de los usuarios no retuitean nada, mientras que un grupo reducido retuitea de forma masiva.

La variable followers y friends presentan varianzas similares y considerables, lo que indica que la cantidad de seguidores y cuentas seguidas también varía bastante entre los usuarios de la base.

En el contexto de salud mental, esta alta variabilidad en el comportamiento digital puede ser relevante, ya que patrones de actividad extrema (ya sea muy alta o muy baja) en redes sociales se han asociado en estudios previos con estados de salud mental alterados.

Matriz de covarianza

X_twitter <- BD_Twitter[, sapply(BD_Twitter, is.numeric)]
cov(X_twitter)
##                     ID  followers     friends favourites      statuses
## ID          33335000.0  258678.29  -1456955.3    4343686  2.790108e+08
## followers     258678.3 3609673.06   3109224.6    -259003 -5.745527e+04
## friends     -1456955.3 3109224.65   3366556.9   -1259019 -1.173205e+07
## favourites   4343685.5 -259002.98  -1259018.5   70443673 -6.372123e+07
## statuses   279010823.1  -57455.27 -11732047.9  -63721226  1.981859e+10
## retweets      898143.9   43092.34    275906.7    8826048 -1.105258e+07
##                retweets
## ID            898143.85
## followers      43092.34
## friends       275906.66
## favourites   8826048.37
## statuses   -11052578.69
## retweets   228604273.27

Interpretación:

La matriz de covarianza permite analizar cómo varían las variables de manera conjunta entre los 20,000 usuarios.

Las varianzas de cada variable, ubicadas en la diagonal, confirman lo observado en el resumen estadístico:

\[ Var(\text{statuses}) = 19{,}818{,}591{,}468 \]

\[ Var(\text{retweets}) = 228{,}604{,}273 \]

\[ Var(\text{favourites}) = 70{,}443{,}673 \]

Estas varianzas enormes reflejan que el comportamiento de los usuarios en la plataforma es muy dispar. No existe un perfil único de usuario de Twitter: las diferencias entre un usuario poco activo y uno extremadamente activo son abismales.

En cuanto a las covarianzas fuera de la diagonal:

La covarianza entre followers y friends es positiva y alta:

\[ Cov(\text{followers}, \text{friends}) = 3{,}109{,}225 \]

Esto indica que los usuarios con más seguidores también tienden a seguir a más personas. Es un patrón lógico en redes sociales donde la reciprocidad en las conexiones es común.

La covarianza entre statuses y friends es negativa:

\[ Cov(\text{statuses}, \text{friends}) = -11{,}732{,}048 \]

Esto sugiere que los usuarios que publican más contenido tienden a seguir a menos cuentas. En el contexto de esta base, podría indicar que los usuarios con alta actividad publicadora tienen un perfil más cerrado o enfocado, mientras que los usuarios que siguen muchas cuentas publican menos.

La covarianza entre statuses y favourites también es negativa:

\[ Cov(\text{statuses}, \text{favourites}) = -63{,}721{,}226 \]

Este resultado es llamativo: los usuarios que más publican son los que menos marcan publicaciones como favoritas. Esto puede indicar que los usuarios con depresión o con alta actividad compulsiva en la plataforma priorizan producir contenido por encima de consumirlo.

Diagramas de dispersión por grupo (depresión / sin depresión)

mi_colores_tw <- c("pink", "purple")
colores_tw    <- mi_colores_tw[as.numeric(BD_Twitter$label)]

pairs(X_twitter,
      col  = colores_tw,
      pch  = 19,
      main = "Diagramas de dispersión por grupo de salud mental")

legend("topright",
       legend = levels(BD_Twitter$label),
       col    = mi_colores_tw,
       pch    = 19)

Interpretación: Los diagramas de dispersión muestran la relación entre las variables de actividad en Twitter, diferenciando a los usuarios con depresión (rosa) y sin depresión (morado).

En general, se observa que los puntos de ambos grupos aparecen muy concentrados cerca del origen en la mayoría de los gráficos, con algunos valores extremos dispersos hacia arriba o hacia la derecha. Esto confirma la alta asimetría de los datos observada en el resumen estadístico.

En los gráficos que involucran la variable ID se aprecia una separación clara entre los dos grupos, ya que el ID simplemente representa el orden en que los usuarios aparecen en la base de datos: los usuarios con depresión tienen IDs bajos (0 a 9,999) y los sin depresión tienen IDs altos (10,000 a 19,999). Esto significa que la variable ID no aporta información real sobre el comportamiento del usuario y debe tomarse con cautela en el análisis.

En las demás variables como followers, friends, favourites, statuses y retweets, los puntos de ambos grupos se superponen considerablemente en la zona de valores bajos, lo que indica que la mayoría de los usuarios, independientemente de si presentan depresión o no, tienen niveles de actividad similares y moderados.

Sin embargo, los valores extremos (los puntos más alejados del origen) tienden a pertenecer al grupo Sin depresión (morado), especialmente en variables como statuses y retweets. Esto podría sugerir que los usuarios sin depresión presentan comportamientos más activos y variables en la plataforma, aunque la separación no es completamente clara y se requiere el análisis discriminante para confirmar si estas diferencias son estadísticamente relevantes.

Prueba de Homocedasticidad (Igualdad de Matrices de Covarianza)

La prueba de Box’s M evalúa si las matrices de covarianza de los grupos son iguales. Las hipótesis del contraste son:

\[ H_0 : \text{Las matrices de covarianza de los grupos son iguales} \]

\[ H_1 : \text{Al menos una matriz de covarianza es diferente} \]

library(biotools)
## Loading required package: MASS
## ---
## biotools version 4.3
boxM(
  BD_Twitter[, sapply(BD_Twitter, is.numeric)],
  BD_Twitter$label
)
## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  BD_Twitter[, sapply(BD_Twitter, is.numeric)]
## Chi-Sq (approx.) = 85110, df = 21, p-value < 2.2e-16

Interpretación: Los resultados de la prueba Box’s M fueron:

\[ \chi^2 = 85{,}110 \]

\[ gl = 21 \]

\[ p\text{-valor} < 2.2 \times 10^{-16} \]

Dado que:

\[ p < 0.05 \]

se rechaza la hipótesis nula \(H_0\).

Esto significa que las matrices de covarianza de los dos grupos (Con depresión y Sin depresión) no son iguales. En otras palabras, la forma en que varían y se relacionan las variables de actividad en Twitter es diferente entre los usuarios con depresión y los usuarios sin depresión.

Desde el punto de vista de la salud mental, este resultado es relevante porque indica que no se trata solo de que los usuarios con depresión tengan más o menos seguidores, o publiquen más o menos. La estructura completa de su comportamiento digital —cómo se relacionan entre sí todas sus variables de actividad— es distinta a la de los usuarios sin depresión.

Este resultado confirma que existen diferencias en los patrones de comportamiento digital entre ambos grupos, aunque el supuesto de homocedasticidad no se cumple, por lo que los resultados del análisis discriminante lineal deben interpretarse con cierta precaución.

Elipses de covarianza

options(rgl.useNULL = TRUE)
library(heplots)
## Loading required package: broom
## 
## Attaching package: 'heplots'
## The following object is masked from 'package:biotools':
## 
##     boxM
covEllipses(
  BD_Twitter[, sapply(BD_Twitter, is.numeric)],
  BD_Twitter$label,
  variables = c(1, 2),
  fill  = TRUE,
  alpha = 0.3,
  col   = c("#F472B6", "#A855F7"),
  lwd   = 2,
  main  = "Elipses de covarianza por grupo de salud mental"
)
## Warning in plot.window(...): "alpha" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "alpha" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "alpha" is not a
## graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "alpha" is not a
## graphical parameter
## Warning in box(...): "alpha" is not a graphical parameter
## Warning in title(...): "alpha" is not a graphical parameter
## Warning in text.default(x, y, label, pos = pos, xpd = xpd, col = col, ...):
## "alpha" is not a graphical parameter
## Warning in text.default(x, y, label, pos = pos, xpd = xpd, col = col, ...):
## "alpha" is not a graphical parameter
## Warning in text.default(x, y, label, pos = pos, xpd = xpd, col = col, ...):
## "alpha" is not a graphical parameter

Interpretación: Las elipses representan la dispersión conjunta de las variables ID y followers para cada grupo de usuarios.

Se observan diferencias claras en la forma y posición de las elipses:

La elipse del grupo Con depresión (rosa) es más grande y circular, lo que indica que los usuarios con depresión presentan mayor variabilidad en la cantidad de seguidores, abarcando desde usuarios con muy pocos hasta algunos con varios miles de seguidores.

La elipse del grupo Sin depresión (morado) es más pequeña y achatada horizontalmente, lo que indica que estos usuarios están más concentrados en un rango de seguidores más estrecho, con menor dispersión en esta variable.

Ambas elipses se traslapan en la zona central del gráfico, lo que confirma que no existe una separación perfecta entre los dos grupos al analizar únicamente estas dos variables. Es decir, conocer solo el ID y la cantidad de seguidores de un usuario no es suficiente para determinar con certeza si presenta depresión o no.

Las diferencias en tamaño y orientación entre las elipses confirman el rechazo del supuesto de igualdad de matrices de covarianza obtenido en la prueba Box’s M:

\[ H_0: \Sigma_{\text{Con depresión}} = \Sigma_{\text{Sin depresión}} \]

con \(p < 2.2 \times 10^{-16}\), lo que indica que los patrones de variabilidad son estructuralmente distintos entre ambos grupos.

Prueba de normalidad (Shapiro-Wilk)

Las hipótesis son:

\[ H_0 : \text{La variable sigue una distribución normal} \]

\[ H_1 : \text{La variable no sigue una distribución normal} \]

Nota Se utiliza una muestra aleatoria de 5000 observaciones porque el test de Shapiro-Wilk solo es válido para tamaños de muestra entre 3 y 5000. Dado que el dataset original contiene 20000 datos por variable, se toma una submuestra para poder aplicar el test correctamente sin violar sus supuestos.

X_twitter_num <- BD_Twitter[, sapply(BD_Twitter, is.numeric)]

lapply(X_twitter_num, function(x) {
  x <- na.omit(x)
  x_sample <- sample(x, 5000)
  shapiro.test(x_sample)
})
## $ID
## 
##  Shapiro-Wilk normality test
## 
## data:  x_sample
## W = 0.95185, p-value < 2.2e-16
## 
## 
## $followers
## 
##  Shapiro-Wilk normality test
## 
## data:  x_sample
## W = 0.29587, p-value < 2.2e-16
## 
## 
## $friends
## 
##  Shapiro-Wilk normality test
## 
## data:  x_sample
## W = 0.20742, p-value < 2.2e-16
## 
## 
## $favourites
## 
##  Shapiro-Wilk normality test
## 
## data:  x_sample
## W = 0.73591, p-value < 2.2e-16
## 
## 
## $statuses
## 
##  Shapiro-Wilk normality test
## 
## data:  x_sample
## W = 0.24105, p-value < 2.2e-16
## 
## 
## $retweets
## 
##  Shapiro-Wilk normality test
## 
## data:  x_sample
## W = 0.064661, p-value < 2.2e-16

Interpretación: Se toma la decisión con base en el p-valor:

\[ \text{Si } p < 0.05 \Rightarrow \text{se rechaza } H_0 \text{ (la variable no es normal)} \]

\[ \text{Si } p > 0.05 \Rightarrow \text{no se rechaza } H_0 \text{ (la variable puede ser normal)} \]

Variable ID

\[ W = 0.9544, \quad p < 2.2 \times 10^{-16} \]

Se rechaza \(H_0\). El ID no sigue una distribución normal. Esto es esperado, ya que el ID es simplemente un número de orden que va de 0 a 19,999 y refleja la posición del usuario en la base de datos, no una característica del comportamiento en Twitter. Por ello, esta variable no debe utilizarse como variable explicativa real en el análisis discriminante.

Variable followers

\[ W = 0.2619, \quad p < 2.2 \times 10^{-16} \]

Se rechaza \(H_0\). La cantidad de seguidores no sigue una distribución normal. Esto es característico de las redes sociales: la mayoría de los usuarios tienen pocos seguidores, mientras que una minoría concentra una audiencia muy grande. Esta distribución altamente asimétrica es la norma en plataformas como Twitter, donde la popularidad no se distribuye de forma equitativa.

Variable friends

\[ W = 0.2054, \quad p < 2.2 \times 10^{-16} \]

Se rechaza \(H_0\). La cantidad de cuentas seguidas tampoco sigue una distribución normal, y presenta la mayor desviación de la normalidad entre todas las variables (W más bajo). Esto indica que la mayoría de los usuarios siguen un número moderado de cuentas, pero existe una minoría que sigue a miles de personas, generando una distribución muy concentrada en valores bajos con una cola larga hacia la derecha.

Variable favourites

\[ W = 0.7378, \quad p < 2.2 \times 10^{-16} \]

Se rechaza \(H_0\). Los favoritos no siguen una distribución normal, aunque su valor de W es mayor que el de followers y friends, lo que indica que su distribución se acerca más a la normal que las anteriores. Aun así, existen usuarios que han marcado decenas de miles de publicaciones como favoritas, mientras que muchos otros apenas interactúan de esta manera.

Variable statuses

\[ W = 0.2445, \quad p < 2.2 \times 10^{-16} \]

Se rechaza \(H_0\). Las publicaciones totales no siguen una distribución normal. Esta es la variable con más variabilidad en toda la base: hay usuarios con apenas tres publicaciones y otros con más de un millón. Esta distribución tan extrema sugiere que la actividad publicadora en Twitter está muy concentrada en un grupo reducido de usuarios muy activos, mientras que la mayoría tiene una presencia más discreta en la plataforma.

Variable retweets

\[ W = 0.0602, \quad p < 2.2 \times 10^{-16} \]

Se rechaza \(H_0\). Los retweets presentan la distribución más alejada de la normalidad de toda la base (W = 0.06, el valor más bajo). Esto se explica porque la mediana de retweets es 0: la mayoría de los usuarios no retuitea absolutamente nada, mientras que unos pocos retuitean cientos de miles de veces. En el contexto de salud mental, un comportamiento de retuiteo extremo puede ser señal de uso compulsivo de la plataforma o de búsqueda intensa de validación social.

Conclusión general

Ninguna de las variables de la base de datos sigue una distribución normal. Todas presentan distribuciones altamente asimétricas con colas largas hacia la derecha, lo cual es un patrón característico del comportamiento en redes sociales. Aunque este resultado indica que el supuesto de normalidad del LDA no se cumple, el análisis discriminante lineal es suficientemente robusto para muestras grandes como esta (\(n = 20{,}000\)), por lo que sus resultados siguen siendo válidos e interpretables.

Gráficos Q-Q

vars_num  <- names(X_twitter_num)
n_vars    <- length(vars_num)
n_cols    <- 2
n_rows    <- ceiling(n_vars / n_cols)

par(mfrow     = c(n_rows, n_cols),
    col.main  = "#3CB371",
    col.lab   = "black",
    cex.main  = 1.2)

colores_qq <- c("#40E0D0", "#7CCD7C", "#FFBBFF", "#FA8072",
                "#87CEEB", "#FFD700", "#DDA0DD", "#98FB98")

for (i in seq_along(vars_num)) {
  col_i <- colores_qq[(i - 1) %% length(colores_qq) + 1]
  qqnorm(X_twitter_num[[ vars_num[i] ]],
         main = paste("QQ Plot -", vars_num[i]),
         pch  = 19,
         col  = col_i)
  qqline(X_twitter_num[[ vars_num[i] ]], col = "red", lwd = 2)
}

Interpretación: Los gráficos Q-Q permiten visualizar de forma gráfica qué tan alejada está cada variable de una distribución normal.

En el gráfico de la variable ID los puntos siguen la línea roja de forma razonablemente aceptable en la parte central, aunque se desvían en los extremos. Esto confirma que el ID tiene una distribución aproximadamente uniforme (como se esperaría de un número de orden), no normal.

En las variables followers, friends, statuses y retweets se observa que la gran mayoría de los puntos se acumulan en la parte inferior izquierda del gráfico, muy por debajo de la línea roja, con solo unos pocos puntos que se disparan hacia arriba en el extremo derecho. Este patrón es la firma visual de una distribución con una cola derecha muy larga: la mayoría de los usuarios tienen valores muy bajos, pero existe un grupo reducido con valores extremadamente altos.

En la variable favourites se observa una desviación moderada de la línea roja, especialmente en la parte superior derecha, donde los puntos se elevan por encima de la línea. Esto indica una concentración de usuarios con muchos favoritos que supera lo que se esperaría bajo una distribución normal.

En general, todos los gráficos Q-Q confirman los resultados de la prueba de Shapiro-Wilk: ninguna variable sigue una distribución normal. Las desviaciones más pronunciadas corresponden a followers, friends, statuses y retweets, que son precisamente las variables con los valores W más bajos en la prueba de normalidad.

Modelo LDA

library(MASS)

# Construir fórmula dinámica con todas las variables numéricas
formula_tw <- as.formula(
  paste("label ~", paste(vars_numericas, collapse = " + "))
)

lda_twitter <- lda(formula_tw, data = BD_Twitter)
lda_twitter
## Call:
## lda(formula_tw, data = BD_Twitter)
## 
## Prior probabilities of groups:
## Con_depresion Sin_depresion 
##           0.5           0.5 
## 
## Group means:
##                    ID followers   friends favourites  statuses retweets
## Con_depresion  4999.5  879.2420 1002.2682   4280.807  9697.184 1056.959
## Sin_depresion 14999.5  921.7259  562.5893   8515.664 79091.656 1818.896
## 
## Coefficients of linear discriminants:
##                      LD1
## ID          3.702640e-04
## followers  -1.187301e-04
## friends     1.278933e-04
## favourites  5.134753e-05
## statuses   -7.180788e-07
## retweets    4.453489e-07

Interpretación: El modelo de Análisis Discriminante Lineal se ajustó utilizando como variable de clasificación label (Con depresión / Sin depresión) y como variables explicativas ID, followers, friends, favourites, statuses y retweets.

Probabilidades a priori

Las probabilidades previas de cada grupo son:

\[ P(\text{Con depresión}) = 0.5 \]

\[ P(\text{Sin depresión}) = 0.5 \]

Esto ocurre porque la base de datos contiene exactamente el mismo número de observaciones en cada grupo (10,000 cada uno), lo cual es una configuración balanceada ideal para el análisis discriminante.

Medias de grupo

Las medias de grupo revelan diferencias importantes en el comportamiento digital entre los dos tipos de usuarios:

La variable statuses muestra la diferencia más pronunciada:

\[ \bar{x}_{\text{statuses, Con depresión}} = 9{,}697 \]

\[ \bar{x}_{\text{statuses, Sin depresión}} = 79{,}092 \]

Esto indica que los usuarios sin depresión han publicado, en promedio, más de ocho veces más contenido que los usuarios con depresión. Este hallazgo puede interpretarse de dos formas: los usuarios sin depresión son más activos en la plataforma, o bien los usuarios con depresión tienen una presencia más pasiva o retraída en Twitter.

La variable friends también muestra una diferencia notable:

\[ \bar{x}_{\text{friends, Con depresión}} = 1{,}002 \]

\[ \bar{x}_{\text{friends, Sin depresión}} = 563 \]

Los usuarios con depresión siguen en promedio a más cuentas que los usuarios sin depresión. Esto podría sugerir un comportamiento de búsqueda de conexión social o de contenido como estrategia de afrontamiento.

La variable favourites también muestra diferencias:

\[ \bar{x}_{\text{favourites, Con depresión}} = 4{,}281 \]

\[ \bar{x}_{\text{favourites, Sin depresión}} = 8{,}516 \]

Los usuarios sin depresión marcan como favoritas aproximadamente el doble de publicaciones que los usuarios con depresión, lo que sugiere que consumen e interactúan más activamente con el contenido de otros.

Coeficientes de la función discriminante

\[ LD_1 = 0.000370(\text{ID}) - 0.000119(\text{followers}) + 0.000128(\text{friends}) + 0.0000513(\text{favourites}) - 0.000000718(\text{statuses}) + 0.000000445(\text{retweets}) \]

La variable con mayor peso relativo en la función discriminante es el ID, lo que refleja que la separación entre grupos está parcialmente determinada por el orden de los datos en la base. Las demás variables tienen coeficientes pequeños, lo que indica que la separación entre grupos no depende de una sola característica de comportamiento, sino de la combinación de todas ellas.

Cálculo de las constantes de las funciones discriminantes

w_tw        <- lda_twitter$scaling[, 1]
medias_tw   <- lda_twitter$means
priors_tw   <- lda_twitter$prior

constantes_tw <- -0.5 * as.vector(medias_tw %*% w_tw) + log(priors_tw)
constantes_tw
## Con_depresion Sin_depresion 
##     -1.737268     -3.641929

Interpretación: Las constantes obtenidas para cada grupo fueron:

\[ c_{\text{Con depresión}} = -1.7373 \]

\[ c_{\text{Sin depresión}} = -3.6419 \]

Las funciones clasificatorias completas quedan definidas como:

\[ \delta_{\text{Con depresión}}(x) = 0.000370(\text{ID}) - 0.000119(\text{followers}) + 0.000128(\text{friends}) + 0.0000513(\text{favourites}) - 7.18 \times 10^{-7}(\text{statuses}) + 4.45 \times 10^{-7}(\text{retweets}) - 1.7373 \]

\[ \delta_{\text{Sin depresión}}(x) = 0.000370(\text{ID}) - 0.000119(\text{followers}) + 0.000128(\text{friends}) + 0.0000513(\text{favourites}) - 7.18 \times 10^{-7}(\text{statuses}) + 4.45 \times 10^{-7}(\text{retweets}) - 3.6419 \]

La constante de la función para Con depresión es mayor (\(-1.7373 > -3.6419\)), lo que indica que, manteniendo constantes las variables de comportamiento, el modelo tiene una inclinación base hacia clasificar un usuario como con depresión antes de considerar sus características digitales. La diferencia entre las constantes es la que establece el umbral de clasificación entre los dos grupos.

Para clasificar a un nuevo usuario, se evalúan ambas funciones y se asigna al grupo cuya función produzca el valor más alto.

Evaluación del modelo

pred_tw <- predict(lda_twitter)

tapply(pred_tw$x[, 1], BD_Twitter$label, mean)
## Con_depresion Sin_depresion 
##     -1.904661      1.904661

Interpretación: Los promedios de la función discriminante por grupo fueron:

\[ \bar{LD1}_{\text{Con depresión}} = -1.9047 \]

\[ \bar{LD1}_{\text{Sin depresión}} = +1.9047 \]

Estos valores indican que la primera función discriminante logra separar claramente los dos grupos a lo largo del eje discriminante: los usuarios con depresión se posicionan en valores negativos de \(LD_1\), mientras que los usuarios sin depresión se ubican en valores positivos y de igual magnitud.

La separación perfectamente simétrica (\(\pm 1.9047\)) es un indicador de que el modelo está bien calibrado y que la función discriminante captura una diferencia sistemática en el comportamiento digital entre ambos grupos. Un usuario cuya combinación de variables produzca un valor de \(LD_1\) negativo será clasificado como Con depresión, y uno con valor positivo será clasificado como Sin depresión.

Matriz de confusión

table(BD_Twitter$label, pred_tw$class)
##                
##                 Con_depresion Sin_depresion
##   Con_depresion          9643           357
##   Sin_depresion            11          9989

Interpretación: La matriz de confusión compara el grupo real de cada usuario con el grupo asignado por el modelo:

\[ \begin{array}{lcc} & \text{Pred. Con dep.} & \text{Pred. Sin dep.} \\ \text{Real Con dep.} & 9{,}643 & 357 \\ \text{Real Sin dep.} & 11 & 9{,}989 \end{array} \]

De los 10,000 usuarios con depresión, el modelo clasificó correctamente a 9,643 y cometió error en solo 357, es decir, clasificó erróneamente a esos 357 usuarios como si no tuvieran depresión cuando en realidad sí la presentaban. En el contexto de salud mental, este tipo de error (falso negativo) es el más preocupante, ya que significaría que una herramienta basada en este modelo dejaría sin identificar a una parte de los usuarios que necesitan atención.

De los 10,000 usuarios sin depresión, el modelo clasificó correctamente a 9,989 y cometió error en apenas 11 casos, clasificándolos incorrectamente como usuarios con depresión. Este tipo de error (falso positivo) es considerablemente menor.

En general, la diagonal principal concentra la gran mayoría de las clasificaciones, lo que indica que el modelo tiene un desempeño muy sólido. Las principales confusiones ocurren al intentar identificar a los usuarios con depresión, lo cual es razonable dado que el comportamiento digital de estos usuarios puede ser más variable y difícil de distinguir.

Exactitud del modelo

mean(BD_Twitter$label == pred_tw$class)
## [1] 0.9816

Interpretación: \[ Exactitud = \frac{\text{Clasificaciones correctas}}{\text{Total de observaciones}} = \frac{9{,}643 + 9{,}989}{20{,}000} = 0.9816 \]

El modelo clasificó correctamente al 98.16% de los usuarios.

Este resultado es notablemente alto e indica que las variables de comportamiento en Twitter (seguidores, amigos, favoritos, publicaciones y retweets) contienen información suficiente para distinguir entre usuarios con y sin depresión con una precisión muy elevada.

Desde una perspectiva de salud pública digital, un modelo con esta exactitud podría ser útil como herramienta de detección temprana de indicios de depresión en redes sociales, identificando perfiles de riesgo a partir del comportamiento observable de los usuarios, sin necesidad de cuestionarios clínicos explícitos.

Validación cruzada

La validación cruzada clasifica cada observación con un modelo que no la vio antes, lo cual evita el sobreajuste y proporciona una estimación más realista del desempeño del modelo. La exactitud con validación cruzada se calcula como:

\[ Exactitud_{CV} = \frac{\text{Número de clasificaciones correctas}}{\text{Total de observaciones}} \]

lda_twitter_cv <- lda(formula_tw,
                      data = BD_Twitter,
                      CV   = TRUE)

table(
  Real     = BD_Twitter$label,
  Predicho = lda_twitter_cv$class
)
##                Predicho
## Real            Con_depresion Sin_depresion
##   Con_depresion          9642           358
##   Sin_depresion            13          9987
mean(BD_Twitter$label == lda_twitter_cv$class)
## [1] 0.98145

Interpretación: La matriz de confusión con validación cruzada mostró los siguientes resultados:

\[ \begin{array}{lcc} & \text{Pred. Con dep.} & \text{Pred. Sin dep.} \\ \text{Real Con dep.} & 9{,}642 & 358 \\ \text{Real Sin dep.} & 12 & 9{,}988 \end{array} \]

La exactitud con validación cruzada fue:

\[ Exactitud_{CV} = 0.9815 \approx 98.15\% \]

Comparando ambos resultados:

Tipo Exactitud
Modelo completo \(98.16\%\)
Validación cruzada \(98.15\%\)

La diferencia entre ambas exactitudes es prácticamente nula (\(0.01\%\)), lo que es un resultado excepcional. Indica que el modelo no presenta sobreajuste: clasifica nuevos usuarios con la misma precisión con la que clasifica los datos con los que fue entrenado.

En el contexto de salud mental, esto significa que el modelo es generalizable: si se aplicara a un conjunto de usuarios de Twitter completamente nuevo, se esperaría mantener una exactitud cercana al 98%, lo cual lo hace potencialmente útil como herramienta de detección a escala en la plataforma.

Clasificación de un usuario nuevo

# Sustituir los valores según las variables disponibles en la base
# Este es un ejemplo genérico — ajustar los nombres y valores reales

nuevo_usuario <- data.frame(
  matrix(
    colMeans(X_twitter_num),   # usa las medias como valores de ejemplo
    nrow = 1,
    dimnames = list(NULL, vars_numericas)
  )
)

predict(lda_twitter, nuevo_usuario)
## $class
## [1] Sin_depresion
## Levels: Con_depresion Sin_depresion
## 
## $posterior
##   Con_depresion Sin_depresion
## 1           0.5           0.5
## 
## $x
##             LD1
## 1 -1.764722e-14

Interpretación: Se evaluó un usuario con valores promedio en todas las variables:

\[ \bar{x}_{\text{ID}} = 9{,}999.5, \quad \bar{x}_{\text{followers}} = 900.5, \quad \bar{x}_{\text{friends}} = 782.4 \]

\[ \bar{x}_{\text{favourites}} = 6{,}398.2, \quad \bar{x}_{\text{statuses}} = 44{,}394.4, \quad \bar{x}_{\text{retweets}} = 1{,}437.9 \]

El modelo asignó probabilidades exactamente iguales a ambos grupos:

\[ P(\text{Con depresión}) = 0.50 \]

\[ P(\text{Sin depresión}) = 0.50 \]

y clasificó al usuario como Sin depresión, aunque con una probabilidad del 50%, lo que representa el caso de máxima incertidumbre en el modelo.

Este resultado es coherente con la estructura de la base: el usuario promedio tiene exactamente el ID 9,999.5, que cae justo en la frontera entre los IDs de los usuarios con depresión (0–9,999) y los sin depresión (10,000–19,999). Esto confirma que la variable ID tiene una influencia artificial en el modelo y que, para un análisis más robusto, sería recomendable excluirla y clasificar nuevos usuarios con valores reales de comportamiento (como seguidores, publicaciones y favoritos) en lugar de utilizar las medias del conjunto de datos.

Conclusiones generales

En este trabajo se aplicó el Análisis Discriminante Lineal (LDA) para estudiar si las variables de comportamiento digital de los usuarios de Twitter permiten clasificarlos en los grupos:

\[ \text{Con depresión} \quad \text{y} \quad \text{Sin depresión} \]

El modelo construyó una función discriminante de la forma:

\[ LD_1 = a_1(\text{ID}) + a_2(\text{followers}) + a_3(\text{friends}) + a_4(\text{favourites}) + a_5(\text{statuses}) + a_6(\text{retweets}) \]

Los resultados mostraron diferencias claras en el comportamiento digital entre ambos grupos. Los usuarios sin depresión presentan, en promedio, un volumen de publicaciones (\(\bar{x} = 79{,}092\)) ocho veces mayor al de los usuarios con depresión (\(\bar{x} = 9{,}697\)), mientras que los usuarios con depresión tienden a seguir a más cuentas (\(\bar{x} = 1{,}002\) vs \(\bar{x} = 563\)) y a interactuar menos con publicaciones de otros.

La exactitud del modelo fue:

\[ Exactitud = 0.9816 \approx 98.16\% \]

con una exactitud en validación cruzada de:

\[ Exactitud_{CV} = 0.9815 \approx 98.15\% \]

La diferencia de apenas \(0.01\%\) entre ambas métricas indica que el modelo no presenta sobreajuste y es altamente generalizable.

En conclusión, el análisis muestra que las variables de comportamiento digital en Twitter contienen información valiosa para identificar patrones asociados con la depresión. El modelo puede utilizarse como herramienta de apoyo en la detección temprana de indicios de depresión en redes sociales, abriendo la posibilidad de intervenciones preventivas a escala digital. Sin embargo, es importante considerar que el modelo se basa en comportamiento observable y no en diagnósticos clínicos, por lo que sus resultados deben complementarse con evaluaciones especializadas.

Base de Lung Cancer

Introducción

El análisis discriminante lineal (LDA) es una técnica estadística multivariada que permite clasificar observaciones en grupos predefinidos a partir de un conjunto de variables cuantitativas. En el contexto de la salud y la medicina, esta técnica resulta especialmente útil para identificar patrones en pacientes que permitan distinguir entre personas que presentan cáncer de pulmón y personas que no lo presentan.

En este análisis se estudia una base de datos de pacientes, donde la variable objetivo clasifica a cada persona en dos grupos:

  • Con cáncer de pulmón (YES)
  • Sin cáncer de pulmón (NO)

El objetivo es determinar si las variables disponibles en la base permiten discriminar adecuadamente entre ambos grupos mediante un análisis discriminante lineal.

Carga de la base de datos en R

# knitr::opts_chunk$set(echo = TRUE)
library(readxl)

BD_LungCancer <- read_excel("/Users/veronicapichardo/Desktop/AM/Bases examen/survey-lung-cancer.xlsx")

Se verifica que los datos se cargaron correctamente observando las primeras filas y la estructura de la base.

head(BD_LungCancer)
str(BD_LungCancer)
## tibble [309 × 16] (S3: tbl_df/tbl/data.frame)
##  $ GENDER               : chr [1:309] "M" "M" "F" "M" ...
##  $ AGE                  : num [1:309] 69 74 59 63 63 75 52 51 68 53 ...
##  $ SMOKING              : num [1:309] 1 2 1 2 1 1 2 2 2 2 ...
##  $ YELLOW_FINGERS       : num [1:309] 2 1 1 2 2 2 1 2 1 2 ...
##  $ ANXIETY              : num [1:309] 2 1 1 2 1 1 1 2 2 2 ...
##  $ PEER_PRESSURE        : num [1:309] 1 1 2 1 1 1 1 2 1 2 ...
##  $ CHRONIC DISEASE      : num [1:309] 1 2 1 1 1 2 1 1 1 2 ...
##  $ FATIGUE              : num [1:309] 2 2 2 1 1 2 2 2 2 1 ...
##  $ ALLERGY              : num [1:309] 1 2 1 1 1 2 1 2 1 2 ...
##  $ WHEEZING             : num [1:309] 2 1 2 1 2 2 2 1 1 1 ...
##  $ ALCOHOL CONSUMING    : num [1:309] 2 1 1 2 1 1 2 1 1 2 ...
##  $ COUGHING             : num [1:309] 2 1 2 1 2 2 2 1 1 1 ...
##  $ SHORTNESS OF BREATH  : num [1:309] 2 2 2 1 2 2 2 2 1 1 ...
##  $ SWALLOWING DIFFICULTY: num [1:309] 2 2 1 2 1 1 1 2 1 2 ...
##  $ CHEST PAIN           : num [1:309] 2 2 2 2 1 1 2 1 1 2 ...
##  $ LUNG_CANCER          : chr [1:309] "YES" "YES" "NO" "NO" ...
dim(BD_LungCancer)
## [1] 309  16
names(BD_LungCancer)
##  [1] "GENDER"                "AGE"                   "SMOKING"              
##  [4] "YELLOW_FINGERS"        "ANXIETY"               "PEER_PRESSURE"        
##  [7] "CHRONIC DISEASE"       "FATIGUE"               "ALLERGY"              
## [10] "WHEEZING"              "ALCOHOL CONSUMING"     "COUGHING"             
## [13] "SHORTNESS OF BREATH"   "SWALLOWING DIFFICULTY" "CHEST PAIN"           
## [16] "LUNG_CANCER"

Preparación de la variable grupo

La variable que indica si el paciente presenta cáncer de pulmón o no es la variable de clasificación del análisis. Se convierte a factor y la base de datos se transforma a data.frame para garantizar compatibilidad con las funciones del análisis discriminante.

Nota importante: Aunque varias variables están codificadas numéricamente (1 y 2), en realidad representan variables categóricas binarias (por ejemplo, 1 = No / 2 = Sí para síntomas como tos, fatiga, ansiedad, etc.). Sin embargo, se mantienen como numéricas para cumplir con los supuestos del modelo LDA, el cual requiere variables cuantitativas.

# La variable de grupo es "LUNG_CANCER" (YES = con cáncer, NO = sin cáncer)
BD_LungCancer$LUNG_CANCER <- as.factor(BD_LungCancer$LUNG_CANCER)

# La variable GENDER también se convierte a factor (M = masculino, F = femenino)
BD_LungCancer$GENDER <- as.factor(BD_LungCancer$GENDER)

BD_LungCancer <- as.data.frame(BD_LungCancer)
str(BD_LungCancer)
## 'data.frame':    309 obs. of  16 variables:
##  $ GENDER               : Factor w/ 2 levels "F","M": 2 2 1 2 1 1 2 1 1 2 ...
##  $ AGE                  : num  69 74 59 63 63 75 52 51 68 53 ...
##  $ SMOKING              : num  1 2 1 2 1 1 2 2 2 2 ...
##  $ YELLOW_FINGERS       : num  2 1 1 2 2 2 1 2 1 2 ...
##  $ ANXIETY              : num  2 1 1 2 1 1 1 2 2 2 ...
##  $ PEER_PRESSURE        : num  1 1 2 1 1 1 1 2 1 2 ...
##  $ CHRONIC DISEASE      : num  1 2 1 1 1 2 1 1 1 2 ...
##  $ FATIGUE              : num  2 2 2 1 1 2 2 2 2 1 ...
##  $ ALLERGY              : num  1 2 1 1 1 2 1 2 1 2 ...
##  $ WHEEZING             : num  2 1 2 1 2 2 2 1 1 1 ...
##  $ ALCOHOL CONSUMING    : num  2 1 1 2 1 1 2 1 1 2 ...
##  $ COUGHING             : num  2 1 2 1 2 2 2 1 1 1 ...
##  $ SHORTNESS OF BREATH  : num  2 2 2 1 2 2 2 2 1 1 ...
##  $ SWALLOWING DIFFICULTY: num  2 2 1 2 1 1 1 2 1 2 ...
##  $ CHEST PAIN           : num  2 2 2 2 1 1 2 1 1 2 ...
##  $ LUNG_CANCER          : Factor w/ 2 levels "NO","YES": 2 2 1 1 1 2 2 2 1 2 ...

Summary

summary(BD_LungCancer)
##  GENDER       AGE           SMOKING      YELLOW_FINGERS    ANXIETY     
##  F:147   Min.   :21.00   Min.   :1.000   Min.   :1.00   Min.   :1.000  
##  M:162   1st Qu.:57.00   1st Qu.:1.000   1st Qu.:1.00   1st Qu.:1.000  
##          Median :62.00   Median :2.000   Median :2.00   Median :1.000  
##          Mean   :62.67   Mean   :1.563   Mean   :1.57   Mean   :1.498  
##          3rd Qu.:69.00   3rd Qu.:2.000   3rd Qu.:2.00   3rd Qu.:2.000  
##          Max.   :87.00   Max.   :2.000   Max.   :2.00   Max.   :2.000  
##  PEER_PRESSURE   CHRONIC DISEASE    FATIGUE         ALLERGY     
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000  
##  Median :2.000   Median :2.000   Median :2.000   Median :2.000  
##  Mean   :1.502   Mean   :1.505   Mean   :1.673   Mean   :1.557  
##  3rd Qu.:2.000   3rd Qu.:2.000   3rd Qu.:2.000   3rd Qu.:2.000  
##  Max.   :2.000   Max.   :2.000   Max.   :2.000   Max.   :2.000  
##     WHEEZING     ALCOHOL CONSUMING    COUGHING     SHORTNESS OF BREATH
##  Min.   :1.000   Min.   :1.000     Min.   :1.000   Min.   :1.000      
##  1st Qu.:1.000   1st Qu.:1.000     1st Qu.:1.000   1st Qu.:1.000      
##  Median :2.000   Median :2.000     Median :2.000   Median :2.000      
##  Mean   :1.557   Mean   :1.557     Mean   :1.579   Mean   :1.641      
##  3rd Qu.:2.000   3rd Qu.:2.000     3rd Qu.:2.000   3rd Qu.:2.000      
##  Max.   :2.000   Max.   :2.000     Max.   :2.000   Max.   :2.000      
##  SWALLOWING DIFFICULTY   CHEST PAIN    LUNG_CANCER
##  Min.   :1.000         Min.   :1.000   NO : 39    
##  1st Qu.:1.000         1st Qu.:1.000   YES:270    
##  Median :1.000         Median :2.000              
##  Mean   :1.469         Mean   :1.557              
##  3rd Qu.:2.000         3rd Qu.:2.000              
##  Max.   :2.000         Max.   :2.000

Interpretación: El resumen estadístico presenta una vista general de los 309 pacientes de la muestra. A continuación se analizan los aspectos más relevantes:

Distribución por género

La muestra está compuesta por 147 mujeres (F) y 162 hombres (M), una distribución relativamente equilibrada. Aunque el género no se incluye directamente en el modelo LDA (por ser variable categórica no binaria numérica), su representación equilibrada evita sesgos de género en los datos.

Edad

\[\bar{x}_{\text{AGE}} = 62.67 \text{ años}, \quad \text{Mín} = 21, \quad \text{Máx} = 87\]

La edad promedio de los pacientes es de casi 63 años, lo cual es consistente con la epidemiología del cáncer de pulmón: esta enfermedad es significativamente más frecuente en adultos de mediana edad y adultos mayores. El rango amplio (de 21 a 87 años) indica que la muestra incluye desde pacientes jóvenes hasta muy longevos.

Variables binarias: síntomas y comportamientos

Las variables como SMOKING, FATIGUE, COUGHING, entre otras, están codificadas como 1 (ausencia) y 2 (presencia). Sus medias permiten estimar qué porcentaje de los pacientes presenta cada característica. Por ejemplo:

\[\bar{x}_{\text{FATIGUE}} = 1.673 \implies \approx 67\% \text{ de los pacientes presenta fatiga}\]

\[\bar{x}_{\text{SWALLOWING DIFFICULTY}} = 1.469 \implies \approx 47\% \text{ de los pacientes tiene dificultad para tragar}\]

La fatiga es el síntoma más extendido, lo cual es clínicamente comprensible: es uno de los síntomas más comunes del cáncer de pulmón avanzado. En contraste, la dificultad para tragar es el menos frecuente, ya que se asocia más con afecciones del esófago que con el cáncer de pulmón en estadios tempranos.

Desbalance en la variable objetivo

\[n_{\text{YES}} = 270 \quad (87.4\%) \qquad n_{\text{NO}} = 39 \quad (12.6\%)\]

Este desbalance es el aspecto más importante del resumen. Más del 87% de los pacientes tiene diagnóstico de cáncer de pulmón, lo que significa que el modelo tiene una tendencia a priori muy fuerte hacia clasificar como positivo. En la práctica, esto implica que una exactitud alta por sí sola no garantiza que el modelo sea útil: un clasificador que dijera “todos tienen cáncer” ya tendría una exactitud del 87.4% sin aprender nada. Por eso, la exactitud del 93.5% del LDA debe complementarse con un análisis de los errores (falsos negativos y falsos positivos).

Análisis de la Suma Total de las Variables

# Seleccionar únicamente variables numéricas para el análisis
vars_numericas_lc <- names(BD_LungCancer)[sapply(BD_LungCancer, is.numeric)]
vars_numericas_lc
##  [1] "AGE"                   "SMOKING"               "YELLOW_FINGERS"       
##  [4] "ANXIETY"               "PEER_PRESSURE"         "CHRONIC DISEASE"      
##  [7] "FATIGUE"               "ALLERGY"               "WHEEZING"             
## [10] "ALCOHOL CONSUMING"     "COUGHING"              "SHORTNESS OF BREATH"  
## [13] "SWALLOWING DIFFICULTY" "CHEST PAIN"
colSums(BD_LungCancer[, vars_numericas_lc])
##                   AGE               SMOKING        YELLOW_FINGERS 
##                 19366                   483                   485 
##               ANXIETY         PEER_PRESSURE       CHRONIC DISEASE 
##                   463                   464                   465 
##               FATIGUE               ALLERGY              WHEEZING 
##                   517                   481                   481 
##     ALCOHOL CONSUMING              COUGHING   SHORTNESS OF BREATH 
##                   481                   488                   507 
## SWALLOWING DIFFICULTY            CHEST PAIN 
##                   454                   481

Interpretación:

Las sumas totales nos indican cuánto acumula cada variable a lo largo de los 309 pacientes. Dado que las variables binarias están codificadas como 1 o 2, el mínimo posible sería 309 (si todos marcaron 1) y el máximo sería 618 (si todos marcaron 2).

  • La variable FATIGUE tiene una suma de 517, lo que significa que una gran cantidad de pacientes reportó tener fatiga (valor 2). Esto cobra sentido porque la fatiga es uno de los síntomas más comunes del cáncer de pulmón.
  • SHORTNESS OF BREATH (dificultad para respirar) también suma 507, lo que apunta a que este síntoma es muy frecuente en la muestra, especialmente en pacientes con cáncer.
  • SWALLOWING DIFFICULTY (dificultad para tragar) es la que suma menos (454), lo que indica que este síntoma es menos frecuente; no todos los pacientes con cáncer de pulmón necesariamente lo presentan.
  • AGE suma 19,366 porque es la única variable continua, siendo su escala completamente diferente al resto.

En resumen, variables con sumas más altas reflejan síntomas muy extendidos en la población estudiada, mientras que las más bajas corresponden a síntomas menos generalizados.

Resumen completo

resumen_completo_lc <- function() {

  resumen_general_lc <- summary(BD_LungCancer)
  datos_numericos_lc <- BD_LungCancer[, sapply(BD_LungCancer, is.numeric)]

  media_lc      <- colMeans(datos_numericos_lc, na.rm = TRUE)
  desviacion_lc <- apply(datos_numericos_lc, 2, sd,  na.rm = TRUE)
  varianza_lc   <- apply(datos_numericos_lc, 2, var, na.rm = TRUE)

  estadisticos_lc <- data.frame(
    Variable            = names(media_lc),
    Media               = media_lc,
    Desviacion_Estandar = desviacion_lc,
    Varianza            = varianza_lc,
    row.names           = NULL
  )

  return(list(
    Resumen      = resumen_general_lc,
    Estadisticos = estadisticos_lc
  ))
}

resultado_lc <- resumen_completo_lc()
resultado_lc$Resumen
##  GENDER       AGE           SMOKING      YELLOW_FINGERS    ANXIETY     
##  F:147   Min.   :21.00   Min.   :1.000   Min.   :1.00   Min.   :1.000  
##  M:162   1st Qu.:57.00   1st Qu.:1.000   1st Qu.:1.00   1st Qu.:1.000  
##          Median :62.00   Median :2.000   Median :2.00   Median :1.000  
##          Mean   :62.67   Mean   :1.563   Mean   :1.57   Mean   :1.498  
##          3rd Qu.:69.00   3rd Qu.:2.000   3rd Qu.:2.00   3rd Qu.:2.000  
##          Max.   :87.00   Max.   :2.000   Max.   :2.00   Max.   :2.000  
##  PEER_PRESSURE   CHRONIC DISEASE    FATIGUE         ALLERGY     
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000  
##  Median :2.000   Median :2.000   Median :2.000   Median :2.000  
##  Mean   :1.502   Mean   :1.505   Mean   :1.673   Mean   :1.557  
##  3rd Qu.:2.000   3rd Qu.:2.000   3rd Qu.:2.000   3rd Qu.:2.000  
##  Max.   :2.000   Max.   :2.000   Max.   :2.000   Max.   :2.000  
##     WHEEZING     ALCOHOL CONSUMING    COUGHING     SHORTNESS OF BREATH
##  Min.   :1.000   Min.   :1.000     Min.   :1.000   Min.   :1.000      
##  1st Qu.:1.000   1st Qu.:1.000     1st Qu.:1.000   1st Qu.:1.000      
##  Median :2.000   Median :2.000     Median :2.000   Median :2.000      
##  Mean   :1.557   Mean   :1.557     Mean   :1.579   Mean   :1.641      
##  3rd Qu.:2.000   3rd Qu.:2.000     3rd Qu.:2.000   3rd Qu.:2.000      
##  Max.   :2.000   Max.   :2.000     Max.   :2.000   Max.   :2.000      
##  SWALLOWING DIFFICULTY   CHEST PAIN    LUNG_CANCER
##  Min.   :1.000         Min.   :1.000   NO : 39    
##  1st Qu.:1.000         1st Qu.:1.000   YES:270    
##  Median :1.000         Median :2.000              
##  Mean   :1.469         Mean   :1.557              
##  3rd Qu.:2.000         3rd Qu.:2.000              
##  Max.   :2.000         Max.   :2.000
resultado_lc$Estadisticos

Interpretación:

La tabla de estadísticos descriptivos presenta la media, desviación estándar y varianza de cada variable numérica de la base.

Medias

Como se observa, la variable AGE tiene la media más alta de todas:

\[\bar{x}_{\text{AGE}} = 62.67 \text{ años}\]

lo que confirma que los pacientes de esta muestra son predominantemente adultos de mediana edad y adultos mayores, el grupo etario con mayor riesgo de desarrollar cáncer de pulmón.

Entre las variables binarias, FATIGUE presenta la media más alta:

\[\bar{x}_{\text{FATIGUE}} = 1.673\]

Esto significa que aproximadamente el 67% de los pacientes reportó fatiga (valor 2). La fatiga es uno de los síntomas sistémicos más frecuentes del cáncer de pulmón, ya que el tumor consume recursos energéticos del organismo y puede generar anemia. Este hallazgo es clínicamente coherente.

Por el contrario, SWALLOWING DIFFICULTY tiene la media más baja entre los síntomas:

\[\bar{x}_{\text{SWALLOWING DIFFICULTY}} = 1.469\]

lo que indica que menos del 47% de los pacientes lo presenta. La dificultad para tragar no es un síntoma primario del cáncer de pulmón, sino que aparece cuando el tumor ha invadido estructuras del mediastino o el esófago, lo que ocurre en estadios más avanzados.

Desviaciones estándar y varianzas

AGE es la variable con mayor varianza:

\[s^2_{\text{AGE}} = 67.41, \qquad s_{\text{AGE}} = 8.21 \text{ años}\]

Esto significa que los pacientes pueden diferir hasta 8 años por encima o por debajo del promedio de manera típica, con casos extremos de hasta 40 años de diferencia respecto a la media. Esta variabilidad en edad puede ser relevante para el modelo, ya que pacientes más jóvenes con cáncer pueden tener perfiles de síntomas distintos a los de pacientes mayores.

Las variables binarias tienen desviaciones estándar notablemente menores y muy similares entre sí, rondando entre 0.47 y 0.50:

\[s_{\text{binaria}} \approx 0.47 - 0.50\]

Esto es esperado: dado que los valores solo pueden ser 1 o 2, la dispersión máxima posible es limitada. El hecho de que todas tengan desviaciones similares indica que ningún síntoma domina la variabilidad sobre los demás; todos aportan información de manera relativamente equitativa, lo cual favorece el uso de todas las variables en el modelo LDA.

Matriz de covarianza

X_lc <- BD_LungCancer[, sapply(BD_LungCancer, is.numeric)]
cov(X_lc)
##                                AGE       SMOKING YELLOW_FINGERS      ANXIETY
## AGE                   67.409048880 -0.3445656285    0.021193208  0.218625226
## SMOKING               -0.344565629  0.2468162905   -0.003593494  0.039875173
## YELLOW_FINGERS         0.021193208 -0.0035934939    0.245954693  0.140535031
## ANXIETY                0.218625226  0.0398751734    0.140535031  0.250809061
## PEER_PRESSURE          0.076829320 -0.0106543941    0.080244189  0.054385744
## CHRONIC DISEASE       -0.051979574 -0.0352099357    0.010213088 -0.002427184
## FATIGUE                0.048659270 -0.0069032909   -0.027508091 -0.044361787
## ALLERGY                0.114350859  0.0004728281   -0.035609213 -0.041304165
## WHEEZING               0.224740470 -0.0319947043   -0.019375447 -0.047797672
## ALCOHOL CONSUMING      0.240974236 -0.0125141848   -0.071323499 -0.041304165
## COUGHING               0.689961333 -0.0318055731   -0.003099651 -0.055877779
## SHORTNESS OF BREATH   -0.069095953  0.0146261505   -0.025249023 -0.034674064
## SWALLOWING DIFFICULTY -0.005211617  0.0076282940    0.085750011  0.122515025
## CHEST PAIN            -0.073960829  0.0296936074   -0.025868953 -0.028317152
##                       PEER_PRESSURE CHRONIC DISEASE       FATIGUE       ALLERGY
## AGE                      0.07682932   -0.0519795738  0.0486592695  0.1143508595
## SMOKING                 -0.01065439   -0.0352099357 -0.0069032909  0.0004728281
## YELLOW_FINGERS           0.08024419    0.0102130879 -0.0275080906 -0.0356092128
## ANXIETY                  0.05438574   -0.0024271845 -0.0443617871 -0.0413041651
## PEER_PRESSURE            0.25080906    0.0121674442  0.0183877611 -0.0203841466
## CHRONIC DISEASE          0.01216744    0.2507880469 -0.0260055479  0.0265098979
## FATIGUE                  0.01838776   -0.0260055479  0.2207371916  0.0007144959
## ALLERGY                 -0.02038415    0.0265098979  0.0007144959  0.2475938301
## WHEEZING                -0.01713739   -0.0124511411  0.0331820283  0.0430483756
## ALCOHOL CONSUMING       -0.03986467    0.0005358719 -0.0447400496  0.0852561678
## COUGHING                -0.02204430   -0.0434056235  0.0341171773  0.0466313622
## SHORTNESS OF BREATH     -0.05298827   -0.0063674190  0.0997352162 -0.0071869878
## SWALLOWING DIFFICULTY    0.09177069    0.0188185601 -0.0311856428 -0.0152986172
## CHEST PAIN              -0.02363090   -0.0092043878 -0.0025322574  0.0592821418
##                           WHEEZING ALCOHOL CONSUMING     COUGHING
## AGE                    0.224740470      0.2409742361  0.689961333
## SMOKING               -0.031994704     -0.0125141848 -0.031805573
## YELLOW_FINGERS        -0.019375447     -0.0713234985 -0.003099651
## ANXIETY               -0.047797672     -0.0413041651 -0.055877779
## PEER_PRESSURE         -0.017137393     -0.0398646661 -0.022044299
## CHRONIC DISEASE       -0.012451141      0.0005358719 -0.043405624
## FATIGUE                0.033182028     -0.0447400496  0.034117177
## ALLERGY                0.043048376      0.0852561678  0.046631362
## WHEEZING               0.247593830      0.0657756483  0.092085908
## ALCOHOL CONSUMING      0.065775648      0.2475938301  0.049878115
## COUGHING               0.092085908      0.0498781154  0.244504686
## SHORTNESS OF BREATH    0.009046778     -0.0429012735  0.065912243
## SWALLOWING DIFFICULTY  0.017168915     -0.0023116043 -0.038950532
## CHEST PAIN             0.036554869      0.0820094145  0.020657336
##                       SHORTNESS OF BREATH SWALLOWING DIFFICULTY   CHEST PAIN
## AGE                          -0.069095953          -0.005211617 -0.073960829
## SMOKING                       0.014626151           0.007628294  0.029693607
## YELLOW_FINGERS               -0.025249023           0.085750011 -0.025868953
## ANXIETY                      -0.034674064           0.122515025 -0.028317152
## PEER_PRESSURE                -0.052988274           0.091770689 -0.023630900
## CHRONIC DISEASE              -0.006367419           0.018818560 -0.009204388
## FATIGUE                       0.099735216          -0.031185643 -0.002532257
## ALLERGY                      -0.007186988          -0.015298617  0.059282142
## WHEEZING                      0.009046778           0.017168915  0.036554869
## ALCOHOL CONSUMING            -0.042901273          -0.002311604  0.082009415
## COUGHING                      0.065912243          -0.038950532  0.020657336
## SHORTNESS OF BREATH           0.230929265          -0.038677342  0.005800025
## SWALLOWING DIFFICULTY        -0.038677342           0.249863405  0.017168915
## CHEST PAIN                    0.005800025           0.017168915  0.247593830

Interpretación:

La matriz de covarianza describe cómo varían las variables de manera conjunta. Los valores en la diagonal principal son las varianzas de cada variable (ya analizadas), mientras que los valores fuera de la diagonal indican si dos variables tienden a aumentar o disminuir al mismo tiempo (covarianza positiva) o de forma opuesta (covarianza negativa).

Covarianzas más altas: relaciones clínicamente relevantes

La covarianza más alta de toda la matriz es entre AGE y COUGHING:

\[\text{Cov}(\text{AGE}, \text{COUGHING}) = 0.690\]

Esto indica que los pacientes de mayor edad tienden a reportar más tos. Desde el punto de vista clínico, esto es coherente: la tos crónica es uno de los síntomas más comunes del cáncer de pulmón, y la enfermedad es más prevalente en adultos mayores. Además, el daño acumulado en el sistema respiratorio a lo largo de los años (por tabaquismo, contaminación o enfermedades previas) hace que la tos sea más frecuente en personas mayores independientemente del diagnóstico.

Otras covarianzas positivas notables con AGE son:

\[\text{Cov}(\text{AGE}, \text{ALCOHOL.CONSUMING}) = 0.241 \qquad \text{Cov}(\text{AGE}, \text{WHEEZING}) = 0.225\]

Ambas indican que los pacientes de mayor edad en esta muestra tienden también a consumir más alcohol y a presentar más sibilancias. Las sibilancias (sonido al respirar) se asocian con obstrucción de las vías respiratorias, lo cual es más común en fumadores de larga data o en pacientes con cáncer de pulmón avanzado.

Covarianzas negativas: relaciones inversas

La covarianza más negativa es entre AGE y SMOKING:

\[\text{Cov}(\text{AGE}, \text{SMOKING}) = -0.345\]

Esto puede parecer contraintuitivo, pero sugiere que en esta muestra los pacientes más jóvenes son los que más fuman actualmente (valor 2), mientras que los pacientes mayores tienen más proporción de valor 1 (podrían haber dejado de fumar). También puede reflejar que muchos pacientes mayores con cáncer ya han abandonado el tabaquismo tras el diagnóstico o por indicación médica.

Independencia entre síntomas

La mayoría de las covarianzas entre pares de síntomas binarios (como ANXIETY y FATIGUE, WHEEZING y COUGHING, etc.) son pequeñas, cercanas a cero. Por ejemplo:

\[\text{Cov}(\text{FATIGUE}, \text{ALLERGY}) = 0.0007\]

Esto indica que los síntomas son relativamente independientes entre sí, es decir, presentar fatiga no predice fuertemente si el paciente tiene o no alergia. Esta independencia es deseable para el LDA, ya que significa que cada variable aporta información propia y no redundante al modelo.

Diagramas de dispersión por grupo (con cáncer / sin cáncer)

mi_colores_lc <- c("pink", "purple")
colores_lc    <- mi_colores_lc[as.numeric(BD_LungCancer$LUNG_CANCER)]

pairs(X_lc,
      col  = colores_lc,
      pch  = 19,
      main = "Diagramas de dispersión por grupo de Lung Cancer")

legend("topright",
       legend = levels(BD_LungCancer$LUNG_CANCER),
       col    = mi_colores_lc,
       pch    = 19)

Interpretación:

Los diagramas de dispersión muestran simultáneamente las relaciones entre todas las variables numéricas de la base, diferenciando con color a los pacientes sin cáncer (rosa) y con cáncer (morado). Cada celda de la matriz corresponde a un par de variables graficadas entre sí.

Dominio visual del grupo con cáncer

Lo primero que salta a la vista es que los puntos morados (YES) llenan casi completamente cada panel. Esto no es un error gráfico, sino el reflejo directo del desbalance entre grupos:

\[n_{\text{YES}} = 270 \quad \text{frente a} \quad n_{\text{NO}} = 39\]

Es decir, por cada paciente sin cáncer, hay aproximadamente 7 pacientes con cáncer en la muestra. Esto implica que cualquier modelo entrenado con estos datos tendrá una tendencia natural a clasificar como positivo, ya que esa es la clase dominante.

Separación entre grupos

En ningún panel se observa una separación perfecta o clara entre los dos grupos de puntos. Esto indica que ninguna variable por sí sola es capaz de distinguir completamente entre pacientes con y sin cáncer de pulmón. Sin embargo, esta situación es común en datos médicos: raramente un único síntoma diagnostica una enfermedad.

Lo que sí se puede observar es que los puntos rosas (NO) tienden a agruparse en la esquina inferior izquierda de varios paneles, particularmente en aquellos que involucran síntomas como FATIGUE, ALLERGY, COUGHING y WHEEZING. Esto significa que los pacientes sin cáncer tienden a tener valor 1 (ausencia del síntoma) en más variables, mientras que los pacientes con cáncer se dispersan más hacia valor 2 (presencia del síntoma).

Variables con mayor separación visual

Aunque ningún par separa perfectamente, algunos paneles muestran más contraste que otros:

  • AGE vs. variables binarias: Los puntos rosas aparecen más distribuidos en edades menores (hay pacientes jóvenes sin cáncer), mientras que los morados dominan en rangos de edad más altos. Esto es coherente con el hecho de que el cáncer de pulmón es más frecuente en adultos mayores.
  • FATIGUE y ALLERGY: En el panel correspondiente a este par, se observa que varios puntos rosas se acumulan en la coordenada (1, 1), es decir, pacientes sin fatiga y sin alergia. Esto sugiere que la ausencia simultánea de estos dos síntomas podría ser un indicador de que el paciente no tiene cáncer.

Justificación del LDA

El hecho de que ninguna variable aísle perfectamente a los grupos justifica precisamente el uso del Análisis Discriminante Lineal: el LDA toma todas las variables en conjunto y encuentra la combinación lineal que maximiza la separación entre grupos. Lo que visualmente aparece como nubes de puntos mezcladas puede separarse de forma mucho más efectiva en el espacio multidimensional que el LDA construye.

Prueba de Homocedasticidad (Igualdad de Matrices de Covarianza)

La prueba de Box’s M evalúa si las matrices de covarianza de los grupos son iguales. Las hipótesis del contraste son:

\[ H_0 : \text{Las matrices de covarianza de los grupos son iguales} \]

\[ H_1 : \text{Al menos una matriz de covarianza es diferente} \]

library(biotools)

boxM(
  BD_LungCancer[, sapply(BD_LungCancer, is.numeric)],
  BD_LungCancer$LUNG_CANCER
)
## 
##  Box's M-test for Homogeneity of Covariance Matrices 
## 
## data:  BD_LungCancer[, sapply(BD_LungCancer, is.numeric)] by BD_LungCancer$LUNG_CANCER 
## Chi-Sq (approx.) = 228.6669, df = 105, p-value = 3.537e-11

Interpretación:

\[ \text{Si } p < 0.05 \Rightarrow \text{se rechaza } H_0 \]

\[ \text{Si } p > 0.05 \Rightarrow \text{no se rechaza } H_0 \]

\[\chi^2 \approx 228.67, \quad gl = 105, \quad p\text{-value} = 3.537 \times 10^{-11}\]

El resultado del test de Box’s M es extremadamente significativo: el valor \(p = 3.537 \times 10^{-11}\) es prácticamente cero, muy por debajo del umbral de \(\alpha = 0.05\). Por lo tanto, se rechaza \(H_0\) con toda contundencia.

Esto significa que las estructuras de variabilidad y correlación entre variables son fundamentalmente distintas en los pacientes con cáncer y sin cáncer. En términos prácticos:

  • Los pacientes con cáncer (YES) presentan una variabilidad interna mucho mayor en casi todas las variables, lo cual tiene sentido clínico: el cáncer de pulmón puede manifestarse de formas muy diversas dependiendo del estadio, tipo histológico, edad del paciente y hábitos de vida.
  • Los pacientes sin cáncer (NO), al ser un grupo más pequeño y homogéneo (\(n = 39\)), tienen una matriz de covarianza más compacta.

Implicación para el LDA

Formalmente, esta violación del supuesto de homocedasticidad significa que el LDA no es el método óptimo para estos datos. Una alternativa sería el Análisis Discriminante Cuadrático (QDA), que permite que cada grupo tenga su propia matriz de covarianza. Sin embargo, el QDA requiere estimar más parámetros y puede ser inestable cuando uno de los grupos es pequeño, como ocurre aquí con el grupo NO (\(n = 39\)). Por ello, el LDA sigue siendo una opción razonable y sus resultados son interpretables, siempre que se tenga presente esta limitación.

Elipses de covarianza

options(rgl.useNULL = TRUE)
library(heplots)

covEllipses(
  BD_LungCancer[, sapply(BD_LungCancer, is.numeric)],
  BD_LungCancer$LUNG_CANCER,
  variables = c(1, 2),
  fill  = TRUE,
  alpha = 0.3,
  col   = c("#F472B6", "#A855F7"),
  lwd   = 2,
  main  = "Elipses de covarianza por grupo de Lung Cancer"
)
## Warning in plot.window(...): "alpha" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "alpha" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "alpha" is not a
## graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "alpha" is not a
## graphical parameter
## Warning in box(...): "alpha" is not a graphical parameter
## Warning in title(...): "alpha" is not a graphical parameter
## Warning in text.default(x, y, label, pos = pos, xpd = xpd, col = col, ...):
## "alpha" is not a graphical parameter
## Warning in text.default(x, y, label, pos = pos, xpd = xpd, col = col, ...):
## "alpha" is not a graphical parameter
## Warning in text.default(x, y, label, pos = pos, xpd = xpd, col = col, ...):
## "alpha" is not a graphical parameter

Interpretación:

Las elipses de covarianza son una representación visual de cómo se distribuyen y varían los dos grupos de pacientes en el espacio formado por las variables AGE (eje X) y SMOKING (eje Y). El centro de cada elipse corresponde a la media del grupo, y su forma refleja la variabilidad y correlación de las variables dentro de ese grupo.

Tamaño de las elipses: variabilidad interna

La elipse del grupo con cáncer (morado/azul) es considerablemente más grande que la del grupo sin cáncer (rosa). Esto indica que:

\[s^2_{\text{YES, AGE}} > s^2_{\text{NO, AGE}} \qquad \text{y} \qquad s^2_{\text{YES, SMOKING}} > s^2_{\text{NO, SMOKING}}\]

En términos prácticos, los pacientes con cáncer de pulmón son un grupo muy heterogéneo: hay personas de distintas edades (desde relativamente jóvenes hasta mayores de 80 años) y con distintos niveles de tabaquismo. Esta diversidad tiene sentido clínico, ya que el cáncer de pulmón puede desarrollarse tanto en fumadores crónicos como en personas con poco o ningún historial de tabaquismo, influenciado por factores genéticos, ambientales y de otro tipo.

Por el contrario, la elipse más compacta del grupo sin cáncer (rosa) sugiere que estos 39 pacientes comparten perfiles más similares entre sí en cuanto a edad y hábito tabáquico.

Posición de los centros: diferencias entre grupos

Los cruces (+) en el interior de cada elipse marcan las medias de cada grupo. Se observa que el centro del grupo YES está desplazado ligeramente hacia la derecha respecto al grupo NO, lo que confirma lo visto en el summary:

\[\bar{x}_{\text{AGE, YES}} = 62.95 \quad > \quad \bar{x}_{\text{AGE, NO}} = 60.74\]

Aunque la diferencia en edad promedio entre grupos es de aproximadamente 2 años, esta diferencia por sí sola no es suficiente para separar los grupos de forma definitiva.

Traslape entre elipses: dificultad de separación

Un aspecto crucial de la gráfica es que las dos elipses se traslapan considerablemente. Esto significa que hay una zona donde coexisten pacientes con y sin cáncer con valores similares de edad y tabaquismo, lo cual hace imposible clasificar correctamente a todos los pacientes usando solo estas dos variables.

Esta observación, combinada con el resultado de Box’s M (\(p < 0.05\)), confirma que las matrices de covarianza de los grupos son distintas y que el LDA opera bajo una violación de su supuesto de homocedasticidad. Sin embargo, también refuerza la necesidad de incluir más variables (los 12 síntomas restantes) para lograr una discriminación efectiva.

Prueba de normalidad (Shapiro-Wilk)

Las hipótesis son:

\[ H_0 : \text{La variable sigue una distribución normal} \]

\[ H_1 : \text{La variable no sigue una distribución normal} \]

X_lc_num <- BD_LungCancer[, sapply(BD_LungCancer, is.numeric)]

lapply(X_lc_num, function(x) {
  x <- na.omit(x)
  # Si hay más de 5000 observaciones se toma una muestra, de lo contrario se usa todo
  if (length(x) > 5000) {
    x <- sample(x, 5000)
  }
  shapiro.test(x)
})
## $AGE
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.97875, p-value = 0.0001524
## 
## 
## $SMOKING
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63067, p-value < 2.2e-16
## 
## 
## $YELLOW_FINGERS
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.62941, p-value < 2.2e-16
## 
## 
## $ANXIETY
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63649, p-value < 2.2e-16
## 
## 
## $PEER_PRESSURE
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63649, p-value < 2.2e-16
## 
## 
## $`CHRONIC DISEASE`
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63646, p-value < 2.2e-16
## 
## 
## $FATIGUE
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.59134, p-value < 2.2e-16
## 
## 
## $ALLERGY
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63181, p-value < 2.2e-16
## 
## 
## $WHEEZING
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63181, p-value < 2.2e-16
## 
## 
## $`ALCOHOL CONSUMING`
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63181, p-value < 2.2e-16
## 
## 
## $COUGHING
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.62728, p-value < 2.2e-16
## 
## 
## $`SHORTNESS OF BREATH`
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.607, p-value < 2.2e-16
## 
## 
## $`SWALLOWING DIFFICULTY`
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63511, p-value < 2.2e-16
## 
## 
## $`CHEST PAIN`
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.63181, p-value < 2.2e-16

Interpretación:

\[ \text{Si } p < 0.05 \Rightarrow \text{se rechaza } H_0 \text{ (la variable no es normal)} \]

\[ \text{Si } p > 0.05 \Rightarrow \text{no se rechaza } H_0 \text{ (la variable puede ser normal)} \]

\[\text{Si } p < 0.05 \Rightarrow \text{se rechaza } H_0 \text{ (la variable NO es normal)}\]

\[\text{Si } p > 0.05 \Rightarrow \text{no se rechaza } H_0 \text{ (la variable puede ser normal)}\]

Los resultados de la prueba de Shapiro-Wilk son contundentes:

  • Todas las variables presentan un \(p\)-value extremadamente pequeño (\(p < 0.05\)), por lo que se rechaza la hipótesis de normalidad en todos los casos.
  • Esto era esperable: las variables binarias (codificadas como 1 o 2) solo pueden tomar dos valores, por lo que nunca seguirán una distribución normal. Son esencialmente variables de tipo Bernoulli.
  • La variable AGE es la única que se aproxima más a la normalidad (\(W = 0.979\), \(p = 0.000152\)), aunque también se rechaza formalmente. Su distribución es más continua que las demás.

Al igual que con la prueba de Box’s M, esta violación del supuesto de normalidad es importante conocerla, pero el LDA sigue siendo ampliamente utilizado y útil incluso cuando no se cumple perfectamente, especialmente con muestras medianas o grandes.

Gráficos Q-Q

vars_num_lc <- names(X_lc_num)
n_vars_lc   <- length(vars_num_lc)
n_cols_lc   <- 2
n_rows_lc   <- ceiling(n_vars_lc / n_cols_lc)

par(mfrow     = c(n_rows_lc, n_cols_lc),
    col.main  = "#3CB371",
    col.lab   = "black",
    cex.main  = 1.2)

colores_qq_lc <- c("#40E0D0", "#7CCD7C", "#FFBBFF", "#FA8072",
                   "#87CEEB", "#FFD700", "#DDA0DD", "#98FB98",
                   "#FFB6C1", "#B0C4DE", "#F0E68C", "#E6E6FA",
                   "#FFDAB9", "#98FB98")
par(mar = c(2, 2, 2, 1))
for (i in seq_along(vars_num_lc)) {
  col_i <- colores_qq_lc[(i - 1) %% length(colores_qq_lc) + 1]
  qqnorm(X_lc_num[[ vars_num_lc[i] ]],
         main = paste("QQ Plot -", vars_num_lc[i]),
         pch  = 19,
         col  = col_i)
  qqline(X_lc_num[[ vars_num_lc[i] ]], col = "red", lwd = 2)
}

Interpretación:

Los gráficos Q-Q (quantile-quantile) comparan la distribución real de cada variable contra lo que se esperaría si siguiera una distribución normal perfecta. Si los puntos cayeran exactamente sobre la línea roja diagonal, la variable sería perfectamente normal. Cualquier desviación sistemática de esa línea indica alejamiento de la normalidad.

Variables binarias: patrón de escalera

Para todas las variables codificadas como 1 o 2 (síntomas y comportamientos como SMOKING, YELLOW_FINGERS, ANXIETY, FATIGUE, etc.), el patrón es idéntico: los puntos forman dos escalones horizontales, uno en la parte baja del eje Y (correspondiente al valor 1) y otro en la parte alta (correspondiente al valor 2), mientras que la línea roja cruza diagonalmente.

Esto es completamente esperado y tiene una explicación directa: estas variables solo toman dos valores posibles, por lo que su distribución es Bernoulli, no normal. Una variable que solo puede valer 1 o 2 nunca podrá ajustarse a una campana de Gauss. El alejamiento de la línea roja no indica un problema en los datos, sino la naturaleza categórica de las variables.

Variable AGE: la más cercana a la normalidad

El gráfico Q-Q de AGE es cualitativamente diferente al del resto. Los puntos siguen más de cerca la línea roja a lo largo del rango central, lo que indica que la distribución de edades en la muestra es aproximadamente normal. Sin embargo, se observan desviaciones en las colas, especialmente en la cola izquierda (pacientes jóvenes):

  • Los puntos en la cola izquierda caen por debajo de la línea roja, lo que indica que hay menos pacientes jóvenes de lo que esperaría una distribución normal. Esto tiene sentido: el cáncer de pulmón es raro en personas menores de 40 años.
  • En la cola derecha (pacientes mayores), los puntos se ajustan bien a la línea, lo que indica que los pacientes más longevos están bien representados.

A pesar de estas desviaciones en las colas, la prueba de Shapiro-Wilk arrojó \(W = 0.979\) para AGE, el valor más cercano a 1 de todas las variables, confirmando que es la que más se aproxima a la normalidad, aunque formalmente se rechace:

\[W_{\text{AGE}} = 0.979, \quad p = 0.000152\]

Implicación para el LDA

El LDA asume que las variables siguen una distribución normal multivariada dentro de cada grupo. Como se observa claramente en los gráficos Q-Q, este supuesto no se cumple para ninguna de las 13 variables binarias, y solo se aproxima en AGE. Sin embargo, como se mencionó anteriormente, el LDA es robusto a esta violación cuando el tamaño de muestra es razonablemente grande, y los resultados de clasificación (93.5% de exactitud) demuestran que el modelo sigue siendo útil en la práctica a pesar de no cumplir formalmente este supuesto.

Modelo LDA

library(MASS)

# 1. Arreglar nombres del dataset
names(BD_LungCancer) <- make.names(names(BD_LungCancer))

# 2. Volver a crear el subconjunto numérico (MUY IMPORTANTE)
X_lc_num <- BD_LungCancer[, sapply(BD_LungCancer, is.numeric)]

# 3. Obtener nombres ya corregidos
vars_numericas_lc <- names(X_lc_num)

# 4. Crear fórmula
formula_lc <- as.formula(
  paste("LUNG_CANCER ~", paste(vars_numericas_lc, collapse = " + "))
)


lda_lc <- lda(formula_lc, data = BD_LungCancer)
lda_lc
## Call:
## lda(formula_lc, data = BD_LungCancer)
## 
## Prior probabilities of groups:
##        NO       YES 
## 0.1262136 0.8737864 
## 
## Group means:
##          AGE  SMOKING YELLOW_FINGERS  ANXIETY PEER_PRESSURE CHRONIC.DISEASE
## NO  60.74359 1.487179       1.333333 1.307692      1.256410        1.358974
## YES 62.95185 1.574074       1.603704 1.525926      1.537037        1.525926
##      FATIGUE  ALLERGY WHEEZING ALCOHOL.CONSUMING COUGHING SHORTNESS.OF.BREATH
## NO  1.487179 1.128205 1.230769          1.179487 1.256410            1.564103
## YES 1.700000 1.618519 1.603704          1.611111 1.625926            1.651852
##     SWALLOWING.DIFFICULTY CHEST.PAIN
## NO               1.128205   1.307692
## YES              1.518519   1.592593
## 
## Coefficients of linear discriminants:
##                               LD1
## AGE                   0.008739491
## SMOKING               0.448612697
## YELLOW_FINGERS        0.733697370
## ANXIETY               0.470822326
## PEER_PRESSURE         0.539319233
## CHRONIC.DISEASE       0.559024598
## FATIGUE               0.921041677
## ALLERGY               0.911857758
## WHEEZING              0.367599366
## ALCOHOL.CONSUMING     1.192037648
## COUGHING              0.648397386
## SHORTNESS.OF.BREATH   0.272467731
## SWALLOWING.DIFFICULTY 0.610744217
## CHEST.PAIN            0.170821647

Interpretación: El modelo LDA construye una función lineal que combina todas las variables para separar lo mejor posible a los pacientes con cáncer de los que no lo tienen.

Probabilidades a priori:

\[P(\text{NO}) = 0.126 \quad \text{y} \quad P(\text{YES}) = 0.874\]

Esto refleja el desbalance de la muestra: el modelo “sabe” de antemano que el 87.4% de los pacientes tiene cáncer. Si no hay información adicional, lo más probable es clasificar a alguien como positivo.

Medias por grupo: Las medias muestran el perfil promedio de cada grupo:

  • Los pacientes con cáncer tienen promedios más altos en casi todos los síntomas. Por ejemplo:
    • FATIGUE: 1.70 (con cáncer) vs. 1.49 (sin cáncer) → los pacientes con cáncer presentan más fatiga.
    • ALLERGY: 1.62 (con cáncer) vs. 1.13 (sin cáncer) → las alergias son mucho más comunes en pacientes con cáncer.
    • WHEEZING: 1.60 vs. 1.23 → las sibilancias también son más frecuentes en el grupo con cáncer.
  • Los pacientes sin cáncer tienen promedios más bajos, lo que indica que presentan menos síntomas en general.

Coeficientes de la función discriminante (\(LD1\)):

La función discriminante tiene la forma:

\[LD1 = 0.009(\text{AGE}) + 0.449(\text{SMOKING}) + 0.734(\text{YELLOW\_FINGERS}) + 0.471(\text{ANXIETY}) + \cdots + 1.192(\text{ALCOHOL.CONSUMING})\]

Los coeficientes indican el peso de cada variable en la separación de los grupos:

  • ALCOHOL.CONSUMING (1.192) tiene el coeficiente más alto, lo que indica que el consumo de alcohol es la variable que más contribuye a discriminar entre pacientes con y sin cáncer. Valores altos de esta variable empujan fuertemente hacia la clasificación como “con cáncer”.
  • FATIGUE (0.921) y ALLERGY (0.912) también tienen coeficientes muy altos, siendo los siguientes síntomas más influyentes en el modelo.
  • CHEST.PAIN (0.171) y SHORTNESS.OF.BREATH (0.272) tienen coeficientes más bajos, lo que indica que, en conjunto con las demás variables, aportan menos información discriminante.
  • AGE (0.009) tiene el coeficiente más pequeño; aunque los pacientes mayores tienden a tener más cáncer, su contribución marginal en el modelo combinado es mínima porque otras variables capturan mejor la diferencia.

Cálculo de las constantes de las funciones discriminantes

w_lc        <- lda_lc$scaling[, 1]
medias_lc   <- lda_lc$means
priors_lc   <- lda_lc$prior

constantes_lc <- -0.5 * as.vector(medias_lc %*% w_lc) + log(priors_lc)
constantes_lc
##        NO       YES 
## -7.389521 -6.679333

Interpretación: Las constantes completan la función de clasificación de cada grupo:

\[c_{NO} = -7.39 \qquad c_{YES} = -6.68\]

Estas constantes actúan como umbrales de partida para cada grupo antes de considerar los valores de las variables del paciente. Un paciente se clasificará en el grupo cuya función discriminante (constante + combinación lineal de sus variables) sea más alta.

  • La constante del grupo YES (-6.68) es mayor que la del grupo NO (-7.39), lo cual refleja que a priori es más probable pertenecer al grupo con cáncer (probabilidad previa del 87.4%). Esto hace que el modelo “favorezca” la clasificación como positivo cuando la evidencia no es concluyente.
  • En la práctica, un nuevo paciente se clasifica como con cáncer si el valor de su función discriminante más la constante de YES supera a la del grupo NO.

\[ LD_1 = a_1(\text{AGE}) + a_2(\text{SMOKING}) + a_3(\text{YELLOW\_FINGERS}) + a_4(\text{ANXIETY}) + a_5(\text{PEER\_PRESSURE}) + a_6(\text{CHRONIC\_DISEASE}) + a_7(\text{FATIGUE}) + a_8(\text{ALLERGY}) + a_9(\text{WHEEZING}) + a_{10}(\text{ALCOHOL.CONSUMING}) + a_{11}(\text{COUGHING}) + a_{12}(\text{SHORTNESS\_OF\_BREATH}) + a_{13}(\text{SWALLOWING\_DIFFICULTY}) + a_{14}(\text{CHEST\_PAIN}) \]

donde cada coeficiente \(a_j\) indica la contribución de la variable correspondiente a la separación entre los grupos.

El modelo genera una función clasificatoria para cada grupo:

\[ c_{\text{YES}} = k_1 \qquad c_{\text{NO}} = k_2 \]

\[ \delta_{\text{YES}}(x) = a_1(\text{AGE}) + a_2(\text{SMOKING}) + \cdots + a_{14}(\text{CHEST\_PAIN}) + c_{\text{YES}} \]

\[ \delta_{\text{NO}}(x) = a_1(\text{AGE}) + a_2(\text{SMOKING}) + \cdots + a_{14}(\text{CHEST\_PAIN}) + c_{\text{NO}} \]

La clasificación se realiza asignando cada observación al grupo cuya función \(\delta_k(x)\) tome el .

Evaluación del modelo

pred_lc <- predict(lda_lc)

tapply(pred_lc$x[, 1], BD_LungCancer$LUNG_CANCER, mean)
##         NO        YES 
## -2.1402031  0.3091404

Interpretación:

Los valores medios de \(LD1\) por grupo son:

\[\bar{LD1}_{NO} = -2.14 \qquad \bar{LD1}_{YES} = 0.31\]

Estos valores muestran cuánto separa la función discriminante a ambos grupos:

  • Los pacientes sin cáncer obtienen en promedio un valor de \(LD1 = -2.14\), es decir, la función los coloca claramente en el lado negativo del eje discriminante.
  • Los pacientes con cáncer obtienen en promedio \(LD1 = 0.31\), ubicándolos en el lado positivo.
  • La diferencia entre ambas medias (\(0.31 - (-2.14) = 2.45\)) indica que la función discriminante sí logra separar los grupos, aunque con cierto traslape. Cuanto mayor sea esta distancia, mejor es la capacidad discriminante del modelo.

Matriz de confusión

table(BD_LungCancer$LUNG_CANCER, pred_lc$class)
##      
##        NO YES
##   NO   28  11
##   YES   9 261

Interpretación:

La matriz de confusión muestra cuántos pacientes fueron clasificados correctamente e incorrectamente por el modelo:

Predicho: NO Predicho: YES
Real: NO 28 11
Real: YES 9 261

Clasificaciones correctas

\[\text{Verdaderos negativos (TN)} = 28 \qquad \text{Verdaderos positivos (TP)} = 261\]

El modelo identificó correctamente a 261 de los 270 pacientes con cáncer, y a 28 de los 39 pacientes sin cáncer.

Clasificaciones incorrectas

\[\text{Falsos positivos (FP)} = 11 \qquad \text{Falsos negativos (FN)} = 9\]

  • Los 11 falsos positivos son pacientes que en realidad no tienen cáncer, pero el modelo los clasificó como si lo tuvieran. En la práctica médica, esto generaría estudios de confirmación adicionales (biopsias, tomografías) innecesarios, generando estrés al paciente y costos al sistema de salud.
  • Los 9 falsos negativos son pacientes que sí tienen cáncer, pero el modelo no los detectó. Este es el error clínicamente más grave, ya que implicaría no tratar a pacientes que realmente lo necesitan, retrasando el diagnóstico y potencialmente afectando su pronóstico de vida.

Sensibilidad y especificidad

A partir de la matriz se pueden calcular métricas adicionales importantes:

\[\text{Sensibilidad} = \frac{TP}{TP + FN} = \frac{261}{261 + 9} = \frac{261}{270} \approx 96.7\%\]

\[\text{Especificidad} = \frac{TN}{TN + FP} = \frac{28}{28 + 11} = \frac{28}{39} \approx 71.8\%\]

La sensibilidad del 96.7% indica que el modelo detecta correctamente al 96.7% de los pacientes que realmente tienen cáncer, lo cual es muy bueno para una herramienta de screening. Sin embargo, la especificidad del 71.8% revela que el modelo tiene más dificultad para identificar correctamente a los pacientes sanos, clasificando incorrectamente a casi 3 de cada 10 personas sin cáncer como si lo tuvieran.

Exactitud del modelo

mean(BD_LungCancer$LUNG_CANCER == pred_lc$class)
## [1] 0.9352751

Interpretación: ### Interpretación

\[\text{Exactitud} = \frac{TP + TN}{n} = \frac{261 + 28}{309} = \frac{289}{309} \approx 93.5\%\]

El modelo clasifica correctamente al 93.5% de los pacientes utilizando los mismos datos con los que fue entrenado. Esta métrica es optimista por naturaleza: el modelo ya “conoce” los datos y puede haber aprendido particularidades específicas de esta muestra que no necesariamente se generalizan a nuevos pacientes.

Sin embargo, este valor también puede contrastarse con una línea base ingenua: si el modelo simplemente predijera “YES” para todos los pacientes, su exactitud sería del 87.4% (la proporción de YES en la muestra). El LDA supera esta línea base en 6.1 puntos porcentuales, lo que indica que efectivamente aprendió patrones útiles de los datos y no solo está aprovechando el desbalance entre grupos.

Validación cruzada

La validación cruzada clasifica cada observación con un modelo que no la vio antes, lo cual evita el sobreajuste y proporciona una estimación más realista del desempeño del modelo.

lda_lc_cv <- lda(formula_lc,
                 data = BD_LungCancer,
                 CV   = TRUE)

table(
  Real     = BD_LungCancer$LUNG_CANCER,
  Predicho = lda_lc_cv$class
)
##      Predicho
## Real   NO YES
##   NO   27  12
##   YES  12 258
mean(BD_LungCancer$LUNG_CANCER == lda_lc_cv$class)
## [1] 0.9223301

Interpretación: Con validación cruzada (leave-one-out), la exactitud desciende ligeramente:

\[\text{Exactitud con CV} = \frac{27 + 258}{309} = \frac{285}{309} \approx 92.2\%\]

La caída de 93.5% a 92.2% representa apenas 1.3 puntos porcentuales de diferencia. Este resultado es muy favorable porque indica que el modelo no está sobreajustado: su capacidad predictiva se mantiene prácticamente igual cuando se evalúa con datos que no vio durante el entrenamiento.

Comparando las matrices de confusión:

Sin CV Con CV
Falsos negativos (FN) 9 12
Falsos positivos (FP) 11 12
Clasificaciones correctas 289 285

Los falsos negativos (pacientes con cáncer no detectados) aumentaron de 9 a 12 con la validación cruzada. Desde el punto de vista clínico, esto significa que en un escenario real el modelo podría dejar sin detectar aproximadamente 12 de cada 309 pacientes con cáncer. Es un número pequeño, pero en medicina cada falso negativo tiene un impacto humano significativo.

La estabilidad del modelo entre entrenamiento y validación cruzada confirma que las variables seleccionadas capturan patrones reales y generalizables del cáncer de pulmón, no solo ruido estadístico de esta muestra particular.

Clasificación de un paciente nuevo

# Se crea un paciente de ejemplo con los valores promedio de cada variable numérica
nuevo_paciente <- data.frame(
  matrix(
    colMeans(X_lc_num),
    nrow     = 1,
    dimnames = list(NULL, vars_numericas_lc)
  )
)

predict(lda_lc, nuevo_paciente)
## $class
## [1] YES
## Levels: NO YES
## 
## $posterior
##           NO       YES
## 1 0.01510795 0.9848921
## 
## $x
##            LD1
## 1 6.638339e-16

Interpretación: Se creó un paciente hipotético con los valores promedio de todas las variables numéricas de la base (es decir, un “paciente típico” de la muestra). El modelo predice que este paciente tiene cáncer de pulmón (YES), con una probabilidad posterior de:

\[P(\text{YES} \mid \text{datos}) \approx 98.5\% \qquad P(\text{NO} \mid \text{datos}) \approx 1.5\%\]

Esto tiene sentido porque:

  1. Las medias de la muestra están dominadas por el grupo con cáncer (87.4% de los pacientes tienen cáncer), por lo que un paciente “promedio” tenderá a parecerse al grupo mayoritario.
  2. Los síntomas promedio (fatiga, tos, sibilancias, etc.) corresponden en mayor medida al perfil clínico de un paciente con cáncer de pulmón.

El valor de \(LD1 \approx 0\) para este paciente promedio indica que se ubica justo en el punto intermedio del eje discriminante, pero la probabilidad a priori tan alta del grupo YES (87.4%) es suficiente para inclinarlo hacia ese grupo.

Conclusiones generales

En este trabajo se aplicó el para estudiar si las variables clínicas y de comportamiento de los pacientes de la base de Lung Cancer permiten clasificarlos en los grupos:

\[ \text{Con cáncer de pulmón (YES)} \quad \text{y} \quad \text{Sin cáncer de pulmón (NO)} \]

El modelo construyó una función discriminante de la forma:

\[ LD_1 = a_1(\text{AGE}) + a_2(\text{SMOKING}) + a_3(\text{YELLOW\_FINGERS}) + a_4(\text{ANXIETY}) + \cdots + a_{14}(\text{CHEST\_PAIN}) \]

Los resultados muestran que existe una clara capacidad de discriminación entre ambos grupos a partir de los síntomas y hábitos evaluados. En particular, variables como el consumo de alcohol, la fatiga y la presencia de alergias presentan un peso importante en la función discriminante, lo que indica que contribuyen significativamente a diferenciar pacientes con y sin cáncer de pulmón.

La exactitud del modelo fue:

\[ Exactitud = 0.935 \approx 93.5\% \]

mientras que la exactitud obtenida mediante validación cruzada fue:

\[ Exactitud_{CV} = 0.922 \approx 92.2\% \]

La diferencia relativamente pequeña entre ambas métricas sugiere que el modelo no presenta problemas graves de sobreajuste y mantiene una buena capacidad de generalización.

No obstante, es importante señalar que los supuestos teóricos del LDA, como la normalidad multivariada y la igualdad de matrices de covarianza, no se cumplen estrictamente en los datos. A pesar de ello, el modelo mantiene un desempeño sólido, lo que evidencia la robustez del método ante ciertas violaciones de sus supuestos.

Adicionalmente, el desbalance en las clases (mayor proporción de pacientes con cáncer) influye en el comportamiento del modelo, generando una mayor tendencia a clasificar observaciones como positivas. Desde una perspectiva clínica, este sesgo puede ser aceptable, ya que el costo de un falso negativo (no detectar cáncer) es considerablemente más alto que el de un falso positivo.

En conclusión, el análisis confirma que las variables clínicas y de comportamiento consideradas contienen información relevante para la clasificación de pacientes con cáncer de pulmón. El modelo LDA puede ser utilizado como una herramienta de apoyo en la detección temprana, aunque sus resultados deben interpretarse con cautela y complementarse con evaluaciones médicas especializadas.