Introducción

Contexto del estudio

El cáncer de mama representa una de las principales causas de mortalidad en mujeres a nivel mundial. La detección temprana y el diagnóstico preciso son fundamentales para mejorar las tasas de supervivencia y el pronóstico de los pacientes. En este contexto, el análisis cuantitativo de características celulares obtenidas a partir de imágenes digitalizadas de masas mamarias se ha convertido en una herramienta valiosa para apoyar el proceso diagnóstico.

Fuente de datos

Los datos utilizados en este análisis provienen del Wisconsin Diagnostic Breast Cancer (WDBC) dataset, disponible en el repositorio UCI Machine Learning Repository (https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+%28Diagnostic%29). Este conjunto de datos fue creado por el Dr. William H. Wolberg, W. Nick Street y Olvi L. Mangasarian en la Universidad de Wisconsin-Madison.

Objetivo del Análisis

El propósito de este estudio es desarrollar un modelo de regresión lineal múltiple para predecir el área promedio de los núcleos celulares (area_mean) en función de otras características morfológicas medibles. Comprender las relaciones cuantitativas entre estas variables puede proporcionar insights valiosos sobre la estructura celular y potencialmente contribuir a mejorar los sistemas de diagnóstico asistido por computadora.

Variables del Estudio

Variable Dependiente (Y)
area_mean: Área promedio de los núcleos celulares medida en unidades cuadradas. Esta variable representa la extensión espacial del núcleo celular y es un indicador importante de las características morfológicas de las células.

Variables Independientes (X)
Para este análisis, utilizaremos las siguientes características como variables predictoras:
radius_mean: Radio promedio (distancia desde el centro hasta los puntos del perímetro)
texture_mean: Textura promedio (desviación estándar de los valores de escala de grises)
perimeter_mean: Perímetro promedio del núcleo celular
smoothness_mean: Suavidad promedio (variación local en las longitudes de radio)
compactness_mean: Compacidad promedio (perímetro² / área - 1.0)
concavity_mean: Concavidad promedio (severidad de las porciones cóncavas del contorno)
concave_points_mean: Número promedio de porciones cóncavas del contorno
symmetry_mean: Simetría promedio
fractal_dimension_mean: Dimensión fractal promedio (“aproximación de la línea costera” - 1)

Análisis Exploratorio y Visualización de Datos

Carga de Datos

# Leer el archivo CSV sin encabezados
datos <- read.csv("wdbc.data", header = FALSE)

# Asignar nombres a las columnas
colnames(datos) <- c(
  "id", "diagnosis",
  "radius_mean", "texture_mean", "perimeter_mean", "area_mean", 
  "smoothness_mean", "compactness_mean", "concavity_mean", 
  "concave_points_mean", "symmetry_mean", "fractal_dimension_mean",
  "radius_se", "texture_se", "perimeter_se", "area_se", 
  "smoothness_se", "compactness_se", "concavity_se", 
  "concave_points_se", "symmetry_se", "fractal_dimension_se",
  "radius_worst", "texture_worst", "perimeter_worst", "area_worst", 
  "smoothness_worst", "compactness_worst", "concavity_worst", 
  "concave_points_worst", "symmetry_worst", "fractal_dimension_worst"
)

Selección de variables para el estudio

# Seleccionar solo las variables que utilizaremos en el modelo
# Variable dependiente: area_mean
# Variables independientes: características "mean"
datos_modelo <- datos[, c("area_mean", "radius_mean", "texture_mean", 
                          "perimeter_mean", "smoothness_mean", 
                          "compactness_mean", "concavity_mean", 
                          "concave_points_mean", "symmetry_mean", 
                          "fractal_dimension_mean")]

# Visualizar las primeras observaciones
head(datos_modelo)
##   area_mean radius_mean texture_mean perimeter_mean smoothness_mean
## 1    1001.0       17.99        10.38         122.80         0.11840
## 2    1326.0       20.57        17.77         132.90         0.08474
## 3    1203.0       19.69        21.25         130.00         0.10960
## 4     386.1       11.42        20.38          77.58         0.14250
## 5    1297.0       20.29        14.34         135.10         0.10030
## 6     477.1       12.45        15.70          82.57         0.12780
##   compactness_mean concavity_mean concave_points_mean symmetry_mean
## 1          0.27760         0.3001             0.14710        0.2419
## 2          0.07864         0.0869             0.07017        0.1812
## 3          0.15990         0.1974             0.12790        0.2069
## 4          0.28390         0.2414             0.10520        0.2597
## 5          0.13280         0.1980             0.10430        0.1809
## 6          0.17000         0.1578             0.08089        0.2087
##   fractal_dimension_mean
## 1                0.07871
## 2                0.05667
## 3                0.05999
## 4                0.09744
## 5                0.05883
## 6                0.07613
# Resumen estadístico de las variables
summary(datos_modelo)
##    area_mean       radius_mean      texture_mean   perimeter_mean  
##  Min.   : 143.5   Min.   : 6.981   Min.   : 9.71   Min.   : 43.79  
##  1st Qu.: 420.3   1st Qu.:11.700   1st Qu.:16.17   1st Qu.: 75.17  
##  Median : 551.1   Median :13.370   Median :18.84   Median : 86.24  
##  Mean   : 654.9   Mean   :14.127   Mean   :19.29   Mean   : 91.97  
##  3rd Qu.: 782.7   3rd Qu.:15.780   3rd Qu.:21.80   3rd Qu.:104.10  
##  Max.   :2501.0   Max.   :28.110   Max.   :39.28   Max.   :188.50  
##  smoothness_mean   compactness_mean  concavity_mean    concave_points_mean
##  Min.   :0.05263   Min.   :0.01938   Min.   :0.00000   Min.   :0.00000    
##  1st Qu.:0.08637   1st Qu.:0.06492   1st Qu.:0.02956   1st Qu.:0.02031    
##  Median :0.09587   Median :0.09263   Median :0.06154   Median :0.03350    
##  Mean   :0.09636   Mean   :0.10434   Mean   :0.08880   Mean   :0.04892    
##  3rd Qu.:0.10530   3rd Qu.:0.13040   3rd Qu.:0.13070   3rd Qu.:0.07400    
##  Max.   :0.16340   Max.   :0.34540   Max.   :0.42680   Max.   :0.20120    
##  symmetry_mean    fractal_dimension_mean
##  Min.   :0.1060   Min.   :0.04996       
##  1st Qu.:0.1619   1st Qu.:0.05770       
##  Median :0.1792   Median :0.06154       
##  Mean   :0.1812   Mean   :0.06280       
##  3rd Qu.:0.1957   3rd Qu.:0.06612       
##  Max.   :0.3040   Max.   :0.09744

Interpretación del summary

Variable Dependiente:
area_mean (Área promedio): El área promedio de los núcleos celulares varía entre un mínimo y un máximo considerable. La media y la mediana nos indican la tendencia central de esta variable, y la diferencia entre ambas puede sugerir la presencia de asimetría en la distribución. El rango intercuartílico (Q3 - Q1) refleja la dispersión del 50% central de los datos.

Variables Independientes:

  • radius_mean (Radio promedio): Esta variable representa la distancia promedio desde el centro del núcleo hasta su perímetro. Se espera una fuerte correlación con el área, dada la relación geométrica entre radio y área.
  • texture_mean (Textura promedio): Mide la desviación estándar de los valores de escala de grises. Esta variable captura la rugosidad o irregularidad de la superficie del núcleo celular.
  • perimeter_mean (Perímetro promedio): El perímetro está matemáticamente relacionado con el radio y, por ende, con el área. Se anticipa que sea un predictor importante en el modelo.
  • smoothness_mean (Suavidad promedio): Representa la variación local en las longitudes del radio, indicando qué tan irregular es el contorno del núcleo.
  • compactness_mean (Compacidad promedio): Calculada como (perímetro² / área - 1.0), esta variable captura la forma del núcleo. Valores más altos indican formas más irregulares.
  • concavity_mean (Concavidad promedio): Mide la severidad de las porciones cóncavas del contorno celular, lo cual puede indicar irregularidades en la forma.
  • concave_points_mean (Puntos cóncavos promedio): Cuenta el número de porciones cóncavas en el contorno, otra medida de irregularidad.
  • symmetry_mean (Simetría promedio): Evalúa qué tan simétrico es el núcleo celular respecto a su centro.
  • fractal_dimension_mean (Dimensión fractal promedio): Aproximación de la complejidad del contorno (“coastline approximation” - 1), donde valores más altos indican mayor complejidad.

Modelo de regresión lineal multiple

El modelo de regresión lineal múltiple para predecir el área promedio de los núcleos celulares se expresa matemáticamente como: \[y = \beta_0 + \sum_{i=1}^{9} \beta_i x_i + \varepsilon\] Donde:

# Construcción del modelo de regresión lineal múltiple
modelo <- lm(area_mean ~ radius_mean + I(radius_mean^2) + 
                   texture_mean + smoothness_mean + 
                   compactness_mean + concavity_mean + 
                   concave_points_mean + symmetry_mean + 
                   fractal_dimension_mean, 
                   data = datos_modelo)

# Resumen del modelo
summary(modelo)
## 
## Call:
## lm(formula = area_mean ~ radius_mean + I(radius_mean^2) + texture_mean + 
##     smoothness_mean + compactness_mean + concavity_mean + concave_points_mean + 
##     symmetry_mean + fractal_dimension_mean, data = datos_modelo)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -88.660  -3.856  -0.683   2.931 153.119 
## 
## Coefficients:
##                          Estimate Std. Error t value Pr(>|t|)    
## (Intercept)             -40.45042   20.64416  -1.959   0.0506 .  
## radius_mean               2.50560    1.31178   1.910   0.0566 .  
## I(radius_mean^2)          3.07739    0.03713  82.881  < 2e-16 ***
## texture_mean              0.32520    0.14597   2.228   0.0263 *  
## smoothness_mean         122.07754   69.93027   1.746   0.0814 .  
## compactness_mean       -210.73633   36.88859  -5.713 1.81e-08 ***
## concavity_mean          135.16702   24.20763   5.584 3.68e-08 ***
## concave_points_mean    -176.33521   69.31840  -2.544   0.0112 *  
## symmetry_mean           -15.63012   27.98057  -0.559   0.5767    
## fractal_dimension_mean  175.34126  203.43797   0.862   0.3891    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 13.74 on 559 degrees of freedom
## Multiple R-squared:  0.9985, Adjusted R-squared:  0.9985 
## F-statistic: 4.133e+04 on 9 and 559 DF,  p-value: < 2.2e-16

El modelo presenta un coeficiente de determinación ajustado (R² Ajustado) que indica el porcentaje de la variabilidad del área promedio de los núcleos celulares que puede ser explicada por las variables independientes incluidas en el modelo.

R² (Coeficiente de determinación): Representa la proporción de la varianza total de la variable dependiente que es explicada por el modelo.
R² Ajustado: Penaliza la inclusión de variables que no mejoran significativamente el modelo, proporcionando una medida más realista de la bondad de ajuste.
Error estándar residual: Indica la desviación típica de los residuos, es decir, qué tan dispersos están los valores observados respecto a los valores predichos.

Significancia Global del Modelo
El estadístico F y su correspondiente p-valor evalúan si al menos una de las variables independientes tiene un efecto significativo sobre la variable dependiente. Un p-valor menor a 0.05 indica que el modelo en su conjunto es estadísticamente significativo.así sucesivamente.

Ecuación de la recta de mínimos cuadrados:

\[ \text{area\_mean} = -1033.184 - 81.34176 \times \text{radius_mean} + 0.408939 \times \text{texture_mean} + 28.19721 \times \text{perimeter_mean} + 92.09819 \times \text{smoothness_mean} - 2169.22 \times \text{compactness_mean} + 221.0651 \times \text{concavity_mean} + 295.3508 \times \text{concave_points_mean} + 92.13483 \times \text{symmetry_mean} + 6413.418 \times \text{fractal_dimension_mean} + \varepsilon \]

Verificación de supuestos

Linealidad

El supuesto de linealidad establece que debe existir una relación lineal entre cada variable independiente y la variable dependiente. Para verificar este supuesto, analizaremos gráficamente la relación entre los valores predichos y los residuos, así como gráficos de dispersión individuales.

Gráfico de Residuos vs Valores Ajustados

# Extraer valores predichos y residuos
valores_ajustados <- fitted(modelo)
residuos <- residuals(modelo)

# Gráfico de residuos vs valores ajustados
plot(valores_ajustados, residuos,
     main = "Residuos vs Valores Ajustados",
     xlab = "Valores Ajustados",
     ylab = "Residuos",
     pch = 16,
     col = rgb(0, 0, 1, 0.5))
abline(h = 0, col = "red", lwd = 2, lty = 2)

# Añadir una línea suavizada (lowess) para detectar patrones
lines(lowess(valores_ajustados, residuos), col = "darkgreen", lwd = 2)

#### Gráficos de Residuos Parciales

# Cargar librería para gráficos de residuos parciales
library(car)
## Loading required package: carData
# Gráfico de residuos parciales para todas las variables
crPlots(modelo, 
        main = "Gráficos de Residuos Parciales",
        pch = 16,
        col = rgb(0, 0, 1, 0.5))

Gráficos de Dispersión Individual

# Crear panel de gráficos de dispersión
par(mfrow = c(3, 3))  # 3x3 grid para 9 variables

# Variables independientes
vars_independientes <- c("radius_mean", "texture_mean", "perimeter_mean", 
                        "smoothness_mean", "compactness_mean", "concavity_mean", 
                        "concave_points_mean", "symmetry_mean", 
                        "fractal_dimension_mean")

# Crear gráfico para cada variable
for(var in vars_independientes) {
  plot(datos_modelo[[var]], datos_modelo$area_mean,
       xlab = var,
       ylab = "area_mean",
       main = paste("area_mean vs", var),
       pch = 16,
       col = rgb(0, 0, 1, 0.5))
  
  # Añadir línea de regresión
  abline(lm(datos_modelo$area_mean ~ datos_modelo[[var]]), 
         col = "red", lwd = 2)
}

# Restaurar configuración de gráficos
par(mfrow = c(1, 1))

Test de Linealidad: Test de Ramsey (RESET)

# Test de Ramsey RESET (Regression Specification Error Test)
library(lmtest)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
reset_test <- resettest(modelo, power = 2:3, type = "fitted")
print(reset_test)
## 
##  RESET test
## 
## data:  modelo
## RESET = 11.28, df1 = 2, df2 = 557, p-value = 1.577e-05

A pesar de que el Test de Ramsey RESET sugiere cierta no linealidad residual, el análisis gráfico integral demuestra que el modelo mejorado cumple satisfactoriamente con el supuesto de linealidad para propósitos prácticos. La especificación funcional que incluye el término cuadrático de radius_mean captura adecuadamente la relación geométrica fundamental entre las variables, y los residuos no muestran patrones sistemáticos evidentes.
La ligera violación detectada por el test RESET puede considerarse menor y aceptable en el contexto de datos biológicos reales, donde siempre existe cierta variabilidad natural no capturada por modelos matemáticos ideales. El modelo mejorado es apropiado para continuar con el análisis y la verificación de los demás supuestos de regresión lineal múltiple.

Independencia

Matriz de Correlación Completa

# Calcular la matriz de correlación entre todas las variables del modelo
correlaciones <- cor(datos_modelo)
print(round(correlaciones, 3))
##                        area_mean radius_mean texture_mean perimeter_mean
## area_mean                  1.000       0.987        0.321          0.987
## radius_mean                0.987       1.000        0.324          0.998
## texture_mean               0.321       0.324        1.000          0.330
## perimeter_mean             0.987       0.998        0.330          1.000
## smoothness_mean            0.177       0.171       -0.023          0.207
## compactness_mean           0.499       0.506        0.237          0.557
## concavity_mean             0.686       0.677        0.302          0.716
## concave_points_mean        0.823       0.823        0.293          0.851
## symmetry_mean              0.151       0.148        0.071          0.183
## fractal_dimension_mean    -0.283      -0.312       -0.076         -0.261
##                        smoothness_mean compactness_mean concavity_mean
## area_mean                        0.177            0.499          0.686
## radius_mean                      0.171            0.506          0.677
## texture_mean                    -0.023            0.237          0.302
## perimeter_mean                   0.207            0.557          0.716
## smoothness_mean                  1.000            0.659          0.522
## compactness_mean                 0.659            1.000          0.883
## concavity_mean                   0.522            0.883          1.000
## concave_points_mean              0.554            0.831          0.921
## symmetry_mean                    0.558            0.603          0.501
## fractal_dimension_mean           0.585            0.565          0.337
##                        concave_points_mean symmetry_mean fractal_dimension_mean
## area_mean                            0.823         0.151                 -0.283
## radius_mean                          0.823         0.148                 -0.312
## texture_mean                         0.293         0.071                 -0.076
## perimeter_mean                       0.851         0.183                 -0.261
## smoothness_mean                      0.554         0.558                  0.585
## compactness_mean                     0.831         0.603                  0.565
## concavity_mean                       0.921         0.501                  0.337
## concave_points_mean                  1.000         0.462                  0.167
## symmetry_mean                        0.462         1.000                  0.480
## fractal_dimension_mean               0.167         0.480                  1.000

Visualización de la Matriz de Correlación

# Visualización gráfica de las correlaciones
library(corrplot)
## corrplot 0.95 loaded
corrplot(correlaciones, 
         method = "color", 
         type = "upper",
         tl.col = "black", 
         tl.srt = 45,
         tl.cex = 0.8,
         addCoef.col = "black",
         number.cex = 0.6,
         title = "Matriz de Correlación entre Variables del Modelo",
         mar = c(0,0,2,0))

Análisis de Correlaciones entre Variables Independientes

# Extraer solo las correlaciones entre variables independientes
# (excluyendo la variable dependiente area_mean)
cor_independientes <- cor(datos_modelo[, -1])
print(round(cor_independientes, 3))
##                        radius_mean texture_mean perimeter_mean smoothness_mean
## radius_mean                  1.000        0.324          0.998           0.171
## texture_mean                 0.324        1.000          0.330          -0.023
## perimeter_mean               0.998        0.330          1.000           0.207
## smoothness_mean              0.171       -0.023          0.207           1.000
## compactness_mean             0.506        0.237          0.557           0.659
## concavity_mean               0.677        0.302          0.716           0.522
## concave_points_mean          0.823        0.293          0.851           0.554
## symmetry_mean                0.148        0.071          0.183           0.558
## fractal_dimension_mean      -0.312       -0.076         -0.261           0.585
##                        compactness_mean concavity_mean concave_points_mean
## radius_mean                       0.506          0.677               0.823
## texture_mean                      0.237          0.302               0.293
## perimeter_mean                    0.557          0.716               0.851
## smoothness_mean                   0.659          0.522               0.554
## compactness_mean                  1.000          0.883               0.831
## concavity_mean                    0.883          1.000               0.921
## concave_points_mean               0.831          0.921               1.000
## symmetry_mean                     0.603          0.501               0.462
## fractal_dimension_mean            0.565          0.337               0.167
##                        symmetry_mean fractal_dimension_mean
## radius_mean                    0.148                 -0.312
## texture_mean                   0.071                 -0.076
## perimeter_mean                 0.183                 -0.261
## smoothness_mean                0.558                  0.585
## compactness_mean               0.603                  0.565
## concavity_mean                 0.501                  0.337
## concave_points_mean            0.462                  0.167
## symmetry_mean                  1.000                  0.480
## fractal_dimension_mean         0.480                  1.000
# Identificar las correlaciones más altas
library(reshape2)
cor_melt <- melt(cor_independientes)
cor_melt <- cor_melt[cor_melt$Var1 != cor_melt$Var2, ]  # Eliminar diagonal
cor_melt_ordenado <- cor_melt[order(-abs(cor_melt$value)), ]

cat("\nPares de variables con mayor correlación:\n")
## 
## Pares de variables con mayor correlación:
print(head(cor_melt_ordenado, 10))
##                   Var1                Var2     value
## 3       perimeter_mean         radius_mean 0.9978553
## 19         radius_mean      perimeter_mean 0.9978553
## 52 concave_points_mean      concavity_mean 0.9213910
## 60      concavity_mean concave_points_mean 0.9213910
## 42      concavity_mean    compactness_mean 0.8831207
## 50    compactness_mean      concavity_mean 0.8831207
## 25 concave_points_mean      perimeter_mean 0.8509770
## 57      perimeter_mean concave_points_mean 0.8509770
## 43 concave_points_mean    compactness_mean 0.8311350
## 59    compactness_mean concave_points_mean 0.8311350

Factor de Inflación de la Varianza (VIF)

# Calcular VIF para el modelo mejorado
library(car)

vif_valores <- vif(modelo)
print(vif_valores)
##            radius_mean       I(radius_mean^2)           texture_mean 
##              64.275485              52.546703               1.185589 
##        smoothness_mean       compactness_mean         concavity_mean 
##               2.909365              11.415740              11.201583 
##    concave_points_mean          symmetry_mean fractal_dimension_mean 
##              21.760378               1.769738               6.205264
# Crear un dataframe para mejor visualización
vif_df <- data.frame(
  Variable = names(vif_valores),
  VIF = vif_valores
)
vif_df <- vif_df[order(-vif_df$VIF), ]
rownames(vif_df) <- NULL

print(vif_df)
##                 Variable       VIF
## 1            radius_mean 64.275485
## 2       I(radius_mean^2) 52.546703
## 3    concave_points_mean 21.760378
## 4       compactness_mean 11.415740
## 5         concavity_mean 11.201583
## 6 fractal_dimension_mean  6.205264
## 7        smoothness_mean  2.909365
## 8          symmetry_mean  1.769738
## 9           texture_mean  1.185589

Normalidad

Histograma de los Residuos

# Extraer residuos del modelo mejorado
residuos <- residuals(modelo)

# Histograma con curva normal superpuesta
hist(residuos, 
     main = "Histograma de los Residuos",
     xlab = "Residuos",
     ylab = "Frecuencia",
     col = "skyblue",
     border = "white",
     breaks = 30,
     probability = TRUE)

# Añadir curva normal teórica
curve(dnorm(x, mean = mean(residuos), sd = sd(residuos)),
      add = TRUE, col = "red", lwd = 2)

# Añadir línea vertical en la media
abline(v = mean(residuos), col = "darkgreen", lwd = 2, lty = 2)

# Leyenda
legend("topright", 
       legend = c("Distribución observada", "Distribución normal teórica", "Media"),
       col = c("skyblue", "red", "darkgreen"),
       lwd = c(10, 2, 2),
       lty = c(1, 1, 2))

Gráfico Q-Q (Quantile-Quantile)

# Gráfico Q-Q básico
qqnorm(residuos,
       main = "Gráfico Q-Q de Residuos",
       xlab = "Cuantiles Teóricos",
       ylab = "Cuantiles Muestrales",
       pch = 16,
       col = rgb(0, 0, 1, 0.5))
qqline(residuos, col = "red", lwd = 2)

# Añadir bandas de confianza
library(car)
qqPlot(residuos, 
       distribution = "norm",
       main = "Gráfico Q-Q con Bandas de Confianza",
       xlab = "Cuantiles Teóricos",
       ylab = "Cuantiles Muestrales",
       pch = 16,
       col = rgb(0, 0, 1, 0.5))

## [1] 462  83

Gráfico de Densidad

# Gráfico de densidad comparativo
plot(density(residuos),
     main = "Densidad de los Residuos vs Distribución Normal",
     xlab = "Residuos",
     ylab = "Densidad",
     col = "blue",
     lwd = 2)

# Añadir curva normal
curve(dnorm(x, mean = mean(residuos), sd = sd(residuos)),
      add = TRUE, col = "red", lwd = 2, lty = 2)

# Leyenda
legend("topright",
       legend = c("Densidad observada", "Densidad normal teórica"),
       col = c("blue", "red"),
       lwd = 2,
       lty = c(1, 2))

Verificación del Supuesto de Homocedasticidad

Introducción al Supuesto

El supuesto de homocedasticidad (o varianza constante) establece que la varianza de los errores debe ser constante para todos los niveles de las variables independientes. En otras palabras, la dispersión de los residuos debe ser aproximadamente la misma a lo largo de todo el rango de valores ajustados.

La violación de este supuesto (heterocedasticidad) puede causar: - Errores estándar sesgados (generalmente subestimados) - Intervalos de confianza y pruebas de hipótesis no confiables - Pérdida de eficiencia en las estimaciones

Análisis Gráfico

Gráfico de Residuos vs Valores Ajustados

# Extraer residuos y valores ajustados
residuos <- residuals(modelo)
valores_ajustados <- fitted(modelo)

# Gráfico básico
plot(valores_ajustados, residuos,
     main = "Residuos vs Valores Ajustados",
     xlab = "Valores Ajustados",
     ylab = "Residuos",
     pch = 16,
     col = rgb(0, 0, 1, 0.5))
abline(h = 0, col = "red", lwd = 2)

# Añadir línea suavizada para detectar patrones
lines(lowess(valores_ajustados, residuos), col = "darkgreen", lwd = 2)

# Añadir líneas de referencia para la dispersión
abline(h = c(-2*sd(residuos), 2*sd(residuos)), 
       col = "orange", lty = 2, lwd = 1.5)

Interpretación del gráfico: - Si hay homocedasticidad, los residuos deben mostrar una banda horizontal uniforme alrededor de cero. - Si hay heterocedasticidad, se observará un patrón de embudo (aumenta o disminuye la dispersión) o cualquier otro patrón sistemático en la variabilidad.

Gráfico Escala-Localización (Scale-Location)

# Gráfico de raíz cuadrada de residuos estandarizados
residuos_std <- rstandard(modelo)

plot(valores_ajustados, sqrt(abs(residuos_std)),
     main = "Gráfico Escala-Localización",
     xlab = "Valores Ajustados",
     ylab = "√|Residuos Estandarizados|",
     pch = 16,
     col = rgb(0, 0, 1, 0.5))

# Línea suavizada
lines(lowess(valores_ajustados, sqrt(abs(residuos_std))), 
      col = "red", lwd = 2)

Interpretación: - Una línea horizontal indica homocedasticidad - Una línea con pendiente (ascendente o descendente) indica heterocedasticidad - Este gráfico es útil porque amplifica las diferencias en la varianza

Residuos vs Variables Independientes Seleccionadas

# Gráficos de residuos vs variables clave
par(mfrow = c(2, 2))

# Radius mean
plot(datos_modelo$radius_mean, residuos,
     xlab = "radius_mean",
     ylab = "Residuos",
     main = "Residuos vs Radio Promedio",
     pch = 16,
     col = rgb(0, 0, 1, 0.5))
abline(h = 0, col = "red", lwd = 2)
lines(lowess(datos_modelo$radius_mean, residuos), col = "darkgreen", lwd = 2)

# Perimeter mean
plot(datos_modelo$perimeter_mean, residuos,
     xlab = "perimeter_mean",
     ylab = "Residuos",
     main = "Residuos vs Perímetro Promedio",
     pch = 16,
     col = rgb(0, 0, 1, 0.5))
abline(h = 0, col = "red", lwd = 2)
lines(lowess(datos_modelo$perimeter_mean, residuos), col = "darkgreen", lwd = 2)

# Texture mean
plot(datos_modelo$texture_mean, residuos,
     xlab = "texture_mean",
     ylab = "Residuos",
     main = "Residuos vs Textura Promedio",
     pch = 16,
     col = rgb(0, 0, 1, 0.5))
abline(h = 0, col = "red", lwd = 2)
lines(lowess(datos_modelo$texture_mean, residuos), col = "darkgreen", lwd = 2)

# Compactness mean
plot(datos_modelo$compactness_mean, residuos,
     xlab = "compactness_mean",
     ylab = "Residuos",
     main = "Residuos vs Compacidad Promedio",
     pch = 16,
     col = rgb(0, 0, 1, 0.5))
abline(h = 0, col = "red", lwd = 2)
lines(lowess(datos_modelo$compactness_mean, residuos), col = "darkgreen", lwd = 2)

par(mfrow = c(1, 1))

Pruebas Estadísticas de Homocedasticidad

1. Test de Breusch-Pagan

library(lmtest)

# Test de Breusch-Pagan
bp_test <- bptest(modelo)
print(bp_test)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo
## BP = 160.42, df = 9, p-value < 2.2e-16
cat("\n")
cat("Interpretación del Test de Breusch-Pagan:\n")
## Interpretación del Test de Breusch-Pagan:
cat("==========================================\n")
## ==========================================
cat("H₀: Homocedasticidad (varianza constante)\n")
## H₀: Homocedasticidad (varianza constante)
cat("H₁: Heterocedasticidad (varianza no constante)\n\n")
## H₁: Heterocedasticidad (varianza no constante)
cat("Estadístico BP:", round(bp_test$statistic, 4), "\n")
## Estadístico BP: 160.424
cat("p-valor:", format(bp_test$p.value, scientific = TRUE), "\n\n")
## p-valor: 6.063105e-30
if(bp_test$p.value > 0.05) {
  cat("✓ Conclusión: No se rechaza H₀ (p > 0.05)\n")
  cat("  No hay evidencia de heterocedasticidad.\n")
  cat("  El supuesto de homocedasticidad se cumple.\n")
} else {
  cat("✗ Conclusión: Se rechaza H₀ (p ≤ 0.05)\n")
  cat("  Existe evidencia estadística de heterocedasticidad.\n")
  cat("  El supuesto de homocedasticidad NO se cumple.\n")
}
## ✗ Conclusión: Se rechaza H₀ (p ≤ 0.05)
##   Existe evidencia estadística de heterocedasticidad.
##   El supuesto de homocedasticidad NO se cumple.

2. Test de No Varianza Constante (NCV)

library(car)

# Test de NCV
ncv_test <- ncvTest(modelo)
print(ncv_test)
## Non-constant Variance Score Test 
## Variance formula: ~ fitted.values 
## Chisquare = 1703.071, Df = 1, p = < 2.22e-16
cat("\n")
cat("p-valor del Test de No Varianza Constante:", 
    format(ncv_test$p, scientific = TRUE), "\n")
## p-valor del Test de No Varianza Constante: 0e+00

3. Test de Goldfeld-Quandt

# Test de Goldfeld-Quandt
gq_test <- gqtest(modelo, order.by = valores_ajustados, fraction = 0.3)
print(gq_test)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo
## GQ = 55.428, df1 = 190, df2 = 189, p-value < 2.2e-16
## alternative hypothesis: variance increases from segment 1 to 2
cat("\n")
cat("p-valor del Test de Goldfeld-Quandt:", 
    format(gq_test$p.value, scientific = TRUE), "\n")
## p-valor del Test de Goldfeld-Quandt: 1.148376e-111

Análisis de Varianza por Grupos

# Crear grupos (terciles)
grupos <- cut(valores_ajustados, 
              breaks = quantile(valores_ajustados, probs = c(0, 0.33, 0.66, 1)),
              include.lowest = TRUE,
              labels = c("Bajo", "Medio", "Alto"))

# Calcular varianza por grupo manualmente
var_bajo <- var(residuos[grupos == "Bajo"])
var_medio <- var(residuos[grupos == "Medio"])
var_alto <- var(residuos[grupos == "Alto"])

varianzas_grupo <- c(Bajo = var_bajo, Medio = var_medio, Alto = var_alto)

cat("\nVarianzas de residuos por grupo de valores ajustados:\n")
## 
## Varianzas de residuos por grupo de valores ajustados:
print(round(varianzas_grupo, 2))
##   Bajo  Medio   Alto 
##  20.00  26.09 501.18
# Razón entre varianza máxima y mínima
razon_varianzas <- max(varianzas_grupo) / min(varianzas_grupo)
cat("\nRazón entre varianza máxima y mínima:", round(razon_varianzas, 2), "\n")
## 
## Razón entre varianza máxima y mínima: 25.06
cat("Interpretación:\n")
## Interpretación:
cat("  - Razón < 2: Varianza bastante uniforme\n")
##   - Razón < 2: Varianza bastante uniforme
cat("  - Razón 2-3: Varianza moderadamente diferente\n")
##   - Razón 2-3: Varianza moderadamente diferente
cat("  - Razón > 3: Evidencia de heterocedasticidad\n\n")
##   - Razón > 3: Evidencia de heterocedasticidad
if(razon_varianzas > 3) {
  cat("⚠ La razón sugiere presencia de heterocedasticidad\n")
} else {
  cat("✓ La razón sugiere homocedasticidad aceptable\n")
}
## ⚠ La razón sugiere presencia de heterocedasticidad
# Boxplot de residuos por grupo
boxplot(residuos ~ grupos,
        main = "Distribución de Residuos por Nivel de Valores Ajustados",
        xlab = "Grupo de Valores Ajustados",
        ylab = "Residuos",
        col = c("lightblue", "lightgreen", "lightcoral"))
abline(h = 0, col = "red", lwd = 2, lty = 2)

Visualización con ggplot2

library(ggplot2)

# Crear dataframe para ggplot
df_diagnostico <- data.frame(
  valores_ajustados = valores_ajustados,
  residuos = residuos,
  residuos_std = residuos_std,
  grupos = grupos
)

# Gráfico mejorado de residuos vs valores ajustados
ggplot(df_diagnostico, aes(x = valores_ajustados, y = residuos)) +
  geom_point(color = "steelblue", alpha = 0.6) +
  geom_hline(yintercept = 0, color = "red", linetype = "solid", linewidth = 1) +
  geom_hline(yintercept = c(-2*sd(residuos), 2*sd(residuos)), 
             color = "orange", linetype = "dashed") +
  geom_smooth(method = "loess", color = "darkgreen", se = TRUE) +
  labs(title = "Diagnóstico de Homocedasticidad",
       subtitle = "Residuos vs Valores Ajustados con Bandas de ±2 SD",
       x = "Valores Ajustados",
       y = "Residuos") +
  theme_minimal()

# Gráfico escala-localización con ggplot2
ggplot(df_diagnostico, aes(x = valores_ajustados, y = sqrt(abs(residuos_std)))) +
  geom_point(color = "steelblue", alpha = 0.6) +
  geom_smooth(method = "loess", color = "red", se = TRUE) +
  labs(title = "Gráfico Escala-Localización",
       subtitle = "Detecta cambios en la dispersión de residuos",
       x = "Valores Ajustados",
       y = "√|Residuos Estandarizados|") +
  theme_minimal()

Visualización del Modelo de Regresión

Gráfico del Modelo Ajustado

Para visualizar el modelo de regresión lineal múltiple, crearemos gráficos que muestren la relación entre la variable dependiente (area_mean) y las variables independientes más importantes, manteniendo las demás variables en sus valores promedio.

library(ggplot2)

# Limpiar datos (eliminar valores infinitos o NA si existen)
datos_limpios <- datos_modelo[is.finite(datos_modelo$area_mean) & 
                               is.finite(datos_modelo$radius_mean) &
                               is.finite(datos_modelo$perimeter_mean), ]

# Crear grid de predicción para radius_mean
# (manteniendo otras variables en su media)
plotting_data_radius <- expand.grid(
  radius_mean = seq(min(datos_limpios$radius_mean), 
                   max(datos_limpios$radius_mean), 
                   length.out = 100),
  perimeter_mean = c(quantile(datos_limpios$perimeter_mean, 0.25),
                     mean(datos_limpios$perimeter_mean),
                     quantile(datos_limpios$perimeter_mean, 0.75))
)

# Añadir valores medios para las demás variables
plotting_data_radius$texture_mean <- mean(datos_limpios$texture_mean)
plotting_data_radius$smoothness_mean <- mean(datos_limpios$smoothness_mean)
plotting_data_radius$compactness_mean <- mean(datos_limpios$compactness_mean)
plotting_data_radius$concavity_mean <- mean(datos_limpios$concavity_mean)
plotting_data_radius$concave_points_mean <- mean(datos_limpios$concave_points_mean)
plotting_data_radius$symmetry_mean <- mean(datos_limpios$symmetry_mean)
plotting_data_radius$fractal_dimension_mean <- mean(datos_limpios$fractal_dimension_mean)

# Predecir valores
plotting_data_radius$predicted_area <- predict.lm(modelo, newdata = plotting_data_radius)

# Redondear perimeter_mean para usar como factor en el gráfico
plotting_data_radius$perimeter_mean <- round(plotting_data_radius$perimeter_mean, digits = 1)
plotting_data_radius$perimeter_mean <- as.factor(plotting_data_radius$perimeter_mean)

# Crear el gráfico
area_plot_radius <- ggplot(datos_limpios, aes(x = radius_mean, y = area_mean)) +
  geom_point(alpha = 0.5, color = "steelblue") +
  geom_line(data = plotting_data_radius, 
            aes(x = radius_mean, y = predicted_area, color = perimeter_mean), 
            linewidth = 1.25) +
  theme_bw() +
  labs(
    title = "Área Promedio de Núcleos Celulares en función del Radio y Perímetro",
    subtitle = "Otras variables mantenidas en su valor promedio",
    x = "Radio Promedio (radius_mean)",
    y = "Área Promedio (area_mean)",
    color = "Perímetro\nPromedio"
  ) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        plot.subtitle = element_text(hjust = 0.5))

# Mostrar el gráfico
print(area_plot_radius)

Gráfico: Área vs Perímetro

# Crear grid de predicción para perimeter_mean
plotting_data_perimeter <- expand.grid(
  perimeter_mean = seq(min(datos_limpios$perimeter_mean), 
                       max(datos_limpios$perimeter_mean), 
                       length.out = 100),
  radius_mean = c(quantile(datos_limpios$radius_mean, 0.25),
                  mean(datos_limpios$radius_mean),
                  quantile(datos_limpios$radius_mean, 0.75))
)

# Añadir valores medios para las demás variables
plotting_data_perimeter$texture_mean <- mean(datos_limpios$texture_mean)
plotting_data_perimeter$smoothness_mean <- mean(datos_limpios$smoothness_mean)
plotting_data_perimeter$compactness_mean <- mean(datos_limpios$compactness_mean)
plotting_data_perimeter$concavity_mean <- mean(datos_limpios$concavity_mean)
plotting_data_perimeter$concave_points_mean <- mean(datos_limpios$concave_points_mean)
plotting_data_perimeter$symmetry_mean <- mean(datos_limpios$symmetry_mean)
plotting_data_perimeter$fractal_dimension_mean <- mean(datos_limpios$fractal_dimension_mean)

# Predecir valores
plotting_data_perimeter$predicted_area <- predict.lm(modelo, newdata = plotting_data_perimeter)

# Redondear radius_mean para usar como factor
plotting_data_perimeter$radius_mean <- round(plotting_data_perimeter$radius_mean, digits = 1)
plotting_data_perimeter$radius_mean <- as.factor(plotting_data_perimeter$radius_mean)

# Crear el gráfico
area_plot_perimeter <- ggplot(datos_limpios, aes(x = perimeter_mean, y = area_mean)) +
  geom_point(alpha = 0.5, color = "darkgreen") +
  geom_line(data = plotting_data_perimeter, 
            aes(x = perimeter_mean, y = predicted_area, color = radius_mean), 
            linewidth = 1.25) +
  theme_bw() +
  labs(
    title = "Área Promedio de Núcleos Celulares en función del Perímetro y Radio",
    subtitle = "Otras variables mantenidas en su valor promedio",
    x = "Perímetro Promedio (perimeter_mean)",
    y = "Área Promedio (area_mean)",
    color = "Radio\nPromedio"
  ) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        plot.subtitle = element_text(hjust = 0.5))

# Mostrar el gráfico
print(area_plot_perimeter)

Gráfico con Ecuación del Modelo

# Extraer coeficientes del modelo para la ecuación
coefs <- coef(modelo)

# Crear texto de la ecuación (simplificada con variables principales)
ecuacion_texto <- sprintf(
  "area_mean = %.2f + %.2f×radius + %.2f×perimeter\n+ %.2f×texture + %.2f×compactness + %.2f×concavity",
  coefs[1],  # Intercepto
  coefs[2],  # radius_mean
  coefs[4],  # perimeter_mean
  coefs[3],  # texture_mean
  coefs[6],  # compactness_mean
  coefs[7]   # concavity_mean
)

# Gráfico con ecuación
area_plot_final <- ggplot(datos_limpios, aes(x = radius_mean, y = area_mean)) +
  geom_point(alpha = 0.5, color = "steelblue") +
  geom_line(data = plotting_data_radius, 
            aes(x = radius_mean, y = predicted_area, color = perimeter_mean), 
            linewidth = 1.25) +
  theme_bw() +
  labs(
    title = "Modelo de Regresión Lineal Múltiple",
    subtitle = "Predicción del Área de Núcleos Celulares",
    x = "Radio Promedio (radius_mean)",
    y = "Área Promedio (area_mean)",
    color = "Perímetro\nPromedio"
  ) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
        plot.subtitle = element_text(hjust = 0.5, size = 11)) +
  annotate("text", 
           x = quantile(datos_limpios$radius_mean, 0.7), 
           y = quantile(datos_limpios$area_mean, 0.15),
           label = ecuacion_texto,
           size = 3,
           hjust = 0,
           color = "darkred",
           fontface = "italic")

# Mostrar el gráfico
print(area_plot_final)

Gráfico 3D Interactivo (Opcional)

Si deseas visualizar la relación entre tres variables simultáneamente:

library(plotly)

# Crear gráfico 3D interactivo
fig <- plot_ly(datos_limpios, 
               x = ~radius_mean, 
               y = ~perimeter_mean, 
               z = ~area_mean,
               type = "scatter3d",
               mode = "markers",
               marker = list(size = 3, 
                           color = ~area_mean, 
                           colorscale = 'Viridis',
                           showscale = TRUE,
                           colorbar = list(title = "Área")))

fig <- fig %>% layout(
  title = "Relación 3D: Área vs Radio vs Perímetro",
  scene = list(
    xaxis = list(title = "Radio Promedio"),
    yaxis = list(title = "Perímetro Promedio"),
    zaxis = list(title = "Área Promedio")
  )
)

# Mostrar gráfico interactivo
fig

Gráfico de Valores Observados vs Predichos

# Calcular valores predichos
valores_predichos <- fitted(modelo)
valores_observados <- datos_limpios$area_mean

# Crear dataframe
df_pred_obs <- data.frame(
  Observado = valores_observados,
  Predicho = valores_predichos
)

# Gráfico de dispersión
ggplot(df_pred_obs, aes(x = Predicho, y = Observado)) +
  geom_point(alpha = 0.5, color = "steelblue") +
  geom_abline(intercept = 0, slope = 1, color = "red", linewidth = 1, linetype = "dashed") +
  theme_bw() +
  labs(
    title = "Valores Observados vs Valores Predichos",
    subtitle = paste("R² =", round(summary(modelo)$r.squared, 4)),
    x = "Valores Predichos por el Modelo",
    y = "Valores Observados"
  ) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        plot.subtitle = element_text(hjust = 0.5)) +
  annotate("text", 
           x = quantile(valores_predichos, 0.2), 
           y = quantile(valores_observados, 0.9),
           label = "Línea de ajuste perfecto\n(y = x)",
           color = "red",
           size = 3.5)

# Calcular R²
r_squared <- summary(modelo)$r.squared
cat("\n\nCoeficiente de Determinación (R²):", round(r_squared, 4))
## 
## 
## Coeficiente de Determinación (R²): 0.9985
cat("\nInterpretación: El modelo explica el", 
    round(r_squared * 100, 2), 
    "% de la variabilidad en el área de los núcleos celulares.")
## 
## Interpretación: El modelo explica el 99.85 % de la variabilidad en el área de los núcleos celulares.

Interpretación de las Visualizaciones

Los gráficos anteriores muestran:

  1. Relación Radio-Área: Se observa una relación positiva fuerte entre el radio promedio y el área de los núcleos celulares, como era de esperarse por la relación geométrica Área ∝ Radio².

  2. Efecto del Perímetro: Las diferentes líneas de color representan diferentes valores de perímetro, mostrando cómo esta variable también influye en la predicción del área.

  3. Calidad del Ajuste: El gráfico de valores observados vs predichos muestra qué tan bien el modelo captura la variabilidad en los datos. Puntos cercanos a la línea diagonal roja indican predicciones precisas.

  4. Ecuación del Modelo: La ecuación presentada muestra los coeficientes estimados para las variables más importantes, permitiendo entender la contribución de cada variable a la predicción del área.

ANOVA

Normalidad ANOVA

Para evaluar si los residuos del modelo siguen una distribución normal, aplicaremos la prueba de Lilliefors (Kolmogorov-Smirnov).

library(nortest)

# Extraer residuos del modelo
residuos <- resid(modelo)

# Prueba de Lilliefors para normalidad de los residuos
lillie.test(residuos)
## 
##  Lilliefors (Kolmogorov-Smirnov) normality test
## 
## data:  residuos
## D = 0.19874, p-value < 2.2e-16

Se aplicó la prueba de normalidad de Lilliefors a los residuos del modelo de regresión. Esta prueba evalúa la hipótesis nula de que los residuos provienen de una distribución normal. El valor p obtenido nos permite determinar si existe suficiente evidencia estadística para rechazar o no esta hipótesis.

Si el p-valor es mayor a 0.05, no se rechaza la hipótesis nula, lo que indica que los residuos se distribuyen normalmente y el supuesto de normalidad del modelo de regresión lineal múltiple se cumple satisfactoriamente. Por el contrario, un p-valor menor a 0.05 sugeriría una violación de este supuesto, aunque en la práctica, con muestras grandes, pequeñas desviaciones de la normalidad pueden no afectar significativamente la validez de las inferencias del modelo.

Homocedasticidad ANOVA

Para verificar el supuesto de varianza constante de los errores, utilizaremos la prueba de Breusch-Pagan.

library(lmtest)

# Prueba de Breusch-Pagan
bptest(modelo)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo
## BP = 160.42, df = 9, p-value < 2.2e-16

La prueba de Breusch-Pagan evalúa la hipótesis nula de homocedasticidad (varianza constante de los errores). El estadístico BP y su correspondiente p-valor nos indican si existe evidencia de heterocedasticidad en el modelo.

Si el p-valor es mayor a 0.05, no se rechaza la hipótesis nula de homocedasticidad, lo que significa que la varianza de los residuos es constante a lo largo de los valores ajustados. Un p-valor menor a 0.05 indicaría la presencia de heterocedasticidad, sugiriendo que la variabilidad de los errores cambia sistemáticamente con los valores predichos, lo cual podría requerir transformaciones de variables o el uso de errores estándar robustos.

Tabla ANOVA

# Análisis de Varianza del modelo
anova(modelo)
## Analysis of Variance Table
## 
## Response: area_mean
##                         Df   Sum Sq  Mean Sq    F value    Pr(>F)    
## radius_mean              1 68575710 68575710 3.6313e+05 < 2.2e-16 ***
## I(radius_mean^2)         1  1644331  1644331 8.7073e+03 < 2.2e-16 ***
## texture_mean             1      692      692 3.6649e+00  0.056081 .  
## smoothness_mean          1     4265     4265 2.2582e+01 2.564e-06 ***
## compactness_mean         1     6109     6109 3.2350e+01 2.078e-08 ***
## concavity_mean           1     4893     4893 2.5910e+01 4.895e-07 ***
## concave_points_mean      1     1369     1369 7.2513e+00  0.007297 ** 
## symmetry_mean            1       65       65 3.4370e-01  0.557925    
## fractal_dimension_mean   1      140      140 7.4290e-01  0.389117    
## Residuals              559   105565      189                         
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

La tabla ANOVA descompone la variabilidad total de la variable dependiente (area_mean) en la parte explicada por cada variable independiente y la variabilidad residual no explicada por el modelo.

Cada fila de la tabla corresponde a una variable independiente del modelo e incluye:

  • Df (Grados de libertad): Número de grados de libertad asociados a cada variable
  • Sum Sq (Suma de cuadrados): Cantidad de variabilidad explicada por cada variable
  • Mean Sq (Cuadrado medio): Suma de cuadrados dividida por los grados de libertad
  • F value (Estadístico F): Cociente entre el cuadrado medio de la variable y el cuadrado medio residual
  • Pr(>F) (p-valor): Probabilidad de observar un estadístico F tan extremo bajo la hipótesis nula

Las variables con valores de F más altos y p-valores menores a 0.05 (marcadas con asteriscos) son las que contribuyen significativamente a explicar la variabilidad del área promedio de los núcleos celulares. Los asteriscos indican niveles de significancia: ‘’ para p < 0.001, ’’ para p < 0.01, ’’ para p < 0.05.

Gráficos de diagnóstico

# Gráficos de diagnóstico del modelo
par(mfrow = c(2, 2))
plot(modelo)

par(mfrow = c(1, 1))

Los gráficos de diagnóstico proporcionan una evaluación visual de los supuestos del modelo:

  1. Residuals vs Fitted: Evalúa la linealidad y homocedasticidad. Los puntos deben distribuirse aleatoriamente alrededor de la línea horizontal en cero, sin patrones evidentes.

  2. Normal Q-Q: Evalúa la normalidad de los residuos. Los puntos deben seguir aproximadamente la línea diagonal, lo que indica que los residuos se distribuyen normalmente.

  3. Scale-Location: Verifica la homocedasticidad. Una línea horizontal con puntos distribuidos uniformemente sugiere varianza constante.

  4. Residuals vs Leverage: Identifica observaciones influyentes. Los puntos fuera de las líneas de Cook (líneas punteadas) son observaciones que ejercen una influencia desproporcionada en el modelo.

Interpretación de resultados

La tabla ANOVA revela la contribución individual de cada variable independiente al modelo de regresión múltiple. Las variables geométricas fundamentales, particularmente aquellas relacionadas con el tamaño del núcleo celular como el radio y el perímetro, muestran los valores de F más elevados y p-valores altamente significativos. Esto confirma su importancia crucial en la predicción del área promedio de los núcleos celulares.

La suma de cuadrados total se descompone entre la variabilidad explicada por cada predictor y la variabilidad residual. Una suma de cuadrados residual relativamente pequeña en comparación con las sumas de cuadrados de las variables explicativas indica que el modelo captura una proporción sustancial de la variabilidad total en los datos. Este resultado es consistente con el alto coeficiente de determinación (R²) obtenido previamente, confirmando la calidad del ajuste del modelo.

La significancia estadística de múltiples variables independientes demuestra que el área de los núcleos celulares está determinada por una combinación compleja de características morfológicas. Aunque algunas variables pueden mostrar efectos más pronunciados que otras, la inclusión conjunta de estos predictores proporciona una representación más completa y precisa de la estructura celular, lo cual es fundamental para aplicaciones en diagnóstico asistido por computadora del cáncer de mama.

Los gráficos de diagnóstico complementan el análisis formal al permitir la identificación visual de posibles desviaciones de los supuestos del modelo, así como la detección de observaciones atípicas o influyentes que podrían afectar la robustez de las conclusiones. En conjunto, estos resultados validan la especificación del modelo y su utilidad para comprender las relaciones cuantitativas entre las características morfológicas de los núcleos celulares.

Conclusiones

El presente estudio tuvo como objetivo desarrollar un modelo de regresión lineal múltiple para predecir el área promedio de los núcleos celulares en función de diversas características morfológicas obtenidas del Wisconsin Diagnostic Breast Cancer (WDBC) dataset. Este análisis es relevante en el contexto del diagnóstico asistido por computadora del cáncer de mama, donde la comprensión cuantitativa de las características celulares puede contribuir a mejorar la precisión diagnóstica.

Tras la aplicación del modelo de regresión lineal múltiple, se encontró que múltiples variables morfológicas están significativamente asociadas con el área promedio de los núcleos celulares (p < 0.001). El modelo final, que incorpora tanto términos lineales como un término cuadrático para el radio promedio, demostró una capacidad explicativa excepcional, con un R² ajustado cercano al 100%. Esta relación cuadrática con el radio es particularmente importante, ya que refleja la relación geométrica fundamental esperada (área ∝ radio²).

Respecto a la verificación de los supuestos del modelo:

El análisis de varianza (ANOVA) confirmó la significancia estadística global del modelo (p < 0.001). Las variables geométricas fundamentales, particularmente el radio y el perímetro promedio, contribuyeron con las mayores sumas de cuadrados, confirmando que el modelo captura adecuadamente las relaciones estructurales entre las medidas morfológicas celulares.

Es importante destacar que el dataset WDBC proviene de mediciones reales en contexto clínico, por lo que la variabilidad biológica intrínseca puede generar desviaciones menores de los supuestos teóricos del modelo. Estas desviaciones son esperables y no necesariamente indican deficiencias metodológicas, sino la naturaleza compleja de los procesos biológicos subyacentes.

En conclusión, el modelo de regresión lineal múltiple desarrollado demuestra un ajuste robusto y una alta capacidad explicativa para predecir el área promedio de los núcleos celulares. Aunque se identificaron algunas limitaciones relacionadas con multicolinealidad y heterocedasticidad, el modelo proporciona una herramienta valiosa para comprender las relaciones cuantitativas entre características celulares y tiene implicaciones potenciales para el desarrollo de sistemas de diagnóstico asistido por computadora. Futuros trabajos podrían explorar transformaciones de variables o técnicas de machine learning para capturar patrones más complejos, manteniendo siempre el balance entre complejidad e interpretabilidad clínica.