Oscar Chullo Puclla | Percy Elbis Colque Caillahua
Palmer Penguins
El conjunto de datos Palmer Penguins (Pingüinos del Archipiélago Palmer) es una base de datos de origen real que se ha convertido en el estándar moderno para la enseñanza de ciencia de datos, visualización y aprendizaje automático, diseñado como una alternativa excelente y éticamente superior al clásico dataset Iris de Fisher.
Origen y Recolección
Los datos fueron recolectados y puestos a disposición del público por la Dra. Kristen Gorman en colaboración con el programa de Investigación Ecológica a Largo Plazo (LTER, por sus siglas en inglés) de la Estación Palmer, en la Antártida. Las observaciones se realizaron durante un período de tres años (2007-2009).
¿Qué contiene la base de datos?
El dataset documenta las características físicas y demográficas de 344 pingüinos adultos en etapa reproductiva, pertenecientes a tres especies diferentes que habitan en el Archipiélago Palmer en la Antártida.
Los datos están segmentados por las siguientes categorías principales:
Especies observadas:
Adélie (Pingüino de Adelia)
Chinstrap (Pingüino Barbijo)
Gentoo (Pingüino Papúa)
Islas de hábitat: Biscoe, Dream y Torgersen.
Variables Morfométricas (Físicas) El núcleo del análisis estadístico de esta base de datos radica en cuatro mediciones físicas fundamentales (generalmente medidas en milímetros y gramos):
Bill Length (Longitud del pico/culmen): La medida desde la base del cráneo hasta la punta del pico superior.
Bill Depth (Profundidad del pico/culmen): El grosor o altura del pico.
Flipper Length (Longitud de la aleta): Medida clave que suele diferenciar drásticamente a ciertas especies (como los Gentoo, que son más grandes).
Body Mass (Masa corporal): El peso del pingüino en gramos.
Adicionalmente, el dataset incluye el sexo (macho/hembra) y el año en que se registró la observación, lo que permite realizar análisis de dimorfismo sexual (diferencias físicas entre géneros) y estudios de clasificación.
# A tibble: 6 × 8
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
<fct> <fct> <dbl> <dbl> <int> <int>
1 Adelie Torgersen 39.1 18.7 181 3750
2 Adelie Torgersen 39.5 17.4 186 3800
3 Adelie Torgersen 40.3 18 195 3250
4 Adelie Torgersen NA NA NA NA
5 Adelie Torgersen 36.7 19.3 193 3450
6 Adelie Torgersen 39.3 20.6 190 3650
# ℹ 2 more variables: sex <fct>, year <int>
De esta base de datos se puede observar las especies a las que pertenecen, la isla proveniente, longitud y profundidad del pico}, logitud de aleta, masa, sexo y año de medición, ademas de que la base de datos presentaba datos perdidos, pero para ejercicio de las actividades requeridas se ha hecho un filtrado de los datos completos quitando los NA.
Luego de tener la separación de nuestros datos según el sexo para la especie Gentoo (Pingüino Papúa) comprobamos que los datos cumplan con los supuestos de normalidad
Test Statistic p.value Method MVN
1 Mardia Skewness 14.961 0.779 asymptotic ✓ Normal
2 Mardia Kurtosis -1.444 0.149 asymptotic ✓ Normal
Código
pM_h$univariate_normality
Test Variable Statistic p.value Normality
1 Shapiro-Wilk bill_length_mm 0.989 0.895 ✓ Normal
2 Shapiro-Wilk bill_depth_mm 0.986 0.736 ✓ Normal
3 Shapiro-Wilk flipper_length_mm 0.974 0.245 ✓ Normal
4 Shapiro-Wilk body_mass_g 0.981 0.511 ✓ Normal
Código
xbar_h <-colMeans(datos_gentoo_h); S_h <-cov(datos_gentoo_h)D2_h <-mahalanobis(datos_gentoo_h, center = xbar_h, cov = S_h)qq_teorico_h <-qchisq(ppoints(nrow(datos_gentoo_h)), df =ncol(datos_gentoo_h))plot(qq_teorico_h, sort(D2_h), pch =19, col ="steelblue",xlab =expression(paste("Cuantiles teoricos ", chi[4]^2)),ylab =expression(paste("Distancias de Mahalanobis ", D[i]^2)),main ="Q-Q chi-cuadrado (Gentoo, hembras)")abline(0, 1, col ="firebrick", lwd =2, lty =2)
A pesar de que para bill_length_mm en machos no se cumpla la normalidad univariante, el test de mardia tanto para machos y hembras, nos indica que los datos en conjunto cumplen con el supuesto de normalidad multivariante, por lo que dado el cumplimiento de la normalidad multivariante se procedió a realizar una prueba mas:
Código
cat("\n================= HOMOGENEIDAD DE COVARIANZAS (BOX'S M - SEXO EN GENTOO) =================\n")
================= HOMOGENEIDAD DE COVARIANZAS (BOX'S M - SEXO EN GENTOO) =================
Box's M-test for Homogeneity of Covariance Matrices
data: datos_gentoo[, vars]
Chi-Sq (approx.) = 26.223, df = 10, p-value = 0.003452
La variabilidad de los datos no es igual entre los pingüinos Gentoo machos y hembras. Es decir, las características que se están midiendo están más dispersas o se relacionan de forma distinta en un sexo en comparación con el otro.
Con esta prueba se corrobora que la separación de los datos por sexo fue un procedimiento adecuado para agrupar características diferenciadas.
for (g in grupos) { df_sub_limpio <- datos_limpios %>%filter(grupo == g) %>% dplyr::select(all_of(vars)) mvn_res_limpio <-mvn(df_sub_limpio, mvn_test ="mardia")cat("\n--- Grupo (Limpio):", g, "---\n")print(mvn_res_limpio$multivariate_normality)}
--- Grupo (Limpio): Adelie_male ---
Test Statistic p.value Method MVN
1 Mardia Skewness 24.423 0.224 asymptotic ✓ Normal
2 Mardia Kurtosis -0.623 0.534 asymptotic ✓ Normal
--- Grupo (Limpio): Adelie_female ---
Test Statistic p.value Method MVN
1 Mardia Skewness 14.164 0.822 asymptotic ✓ Normal
2 Mardia Kurtosis -0.788 0.431 asymptotic ✓ Normal
--- Grupo (Limpio): Gentoo_female ---
Test Statistic p.value Method MVN
1 Mardia Skewness 14.961 0.779 asymptotic ✓ Normal
2 Mardia Kurtosis -1.444 0.149 asymptotic ✓ Normal
--- Grupo (Limpio): Gentoo_male ---
Test Statistic p.value Method MVN
1 Mardia Skewness 15.457 0.750 asymptotic ✓ Normal
2 Mardia Kurtosis -0.831 0.406 asymptotic ✓ Normal
--- Grupo (Limpio): Chinstrap_female ---
Test Statistic p.value Method MVN
1 Mardia Skewness 10.771 0.952 asymptotic ✓ Normal
2 Mardia Kurtosis -0.217 0.828 asymptotic ✓ Normal
--- Grupo (Limpio): Chinstrap_male ---
Test Statistic p.value Method MVN
1 Mardia Skewness 21.092 0.392 asymptotic ✓ Normal
2 Mardia Kurtosis 0.040 0.968 asymptotic ✓ Normal
Código
## -----------------------------------------------------------------------## 2. HOMOGENEIDAD DE COVARIANZAS (BOX'S M) SOBRE DATOS LIMPIOS## -----------------------------------------------------------------------# Separamos los datos limpios por sexo para prepararlos para el MANOVAdatos_limpios_h <- datos_limpios %>%filter(sex =="female")datos_limpios_m <- datos_limpios %>%filter(sex =="male")cat("\n================= TEST DE BOX (M): HEMBRAS =================\n")
================= TEST DE BOX (M): HEMBRAS =================
Box's M-test for Homogeneity of Covariance Matrices
data: datos_limpios_m[, vars]
Chi-Sq (approx.) = 41.319, df = 20, p-value = 0.003389
Código
## -----------------------------------------------------------------------## 3. MANOVA: COMPARACION DE LAS 3 ESPECIES (SOBRE DATOS LIMPIOS)## -----------------------------------------------------------------------cat("\n================= MANOVA: DIFERENCIAS ENTRE ESPECIES (HEMBRAS LIMPIAS) =================\n")
================= MANOVA: DIFERENCIAS ENTRE ESPECIES (HEMBRAS LIMPIAS) =================
Código
modelo_h_limpio <-manova(cbind(bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g) ~ species,data = datos_limpios_h)# Imprimimos Pillai como estadistico principal debido a Box's Mcat("\n--- Traza de Pillai (Recomendado por heterogeneidad) ---\n")
--- Traza de Pillai (Recomendado por heterogeneidad) ---
Código
print(summary(modelo_h_limpio, test ="Pillai"))
Df Pillai approx F num Df den Df Pr(>F)
species 2 1.6306 175.46 8 318 < 2.2e-16 ***
Residuals 161
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Código
cat("\n--- Wilks (Para comparacion) ---\n")
--- Wilks (Para comparacion) ---
Código
print(summary(modelo_h_limpio, test ="Wilks"))
Df Wilks approx F num Df den Df Pr(>F)
species 2 0.015728 275.46 8 316 < 2.2e-16 ***
Residuals 161
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Código
cat("\n================= MANOVA: DIFERENCIAS ENTRE ESPECIES (MACHOS LIMPIOS) =================\n")
================= MANOVA: DIFERENCIAS ENTRE ESPECIES (MACHOS LIMPIOS) =================
Código
modelo_m_limpio <-manova(cbind(bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g) ~ species,data = datos_limpios_m)cat("\n--- Traza de Pillai (Recomendado por heterogeneidad) ---\n")
--- Traza de Pillai (Recomendado por heterogeneidad) ---
Código
print(summary(modelo_m_limpio, test ="Pillai"))
Df Pillai approx F num Df den Df Pr(>F)
species 2 1.7279 255.59 8 322 < 2.2e-16 ***
Residuals 163
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Código
cat("\n--- Wilks (Para comparacion) ---\n")
--- Wilks (Para comparacion) ---
Código
print(summary(modelo_m_limpio, test ="Wilks"))
Df Wilks approx F num Df den Df Pr(>F)
species 2 0.013441 305.02 8 320 < 2.2e-16 ***
Residuals 163
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Código
cat("\n================= ANOVAS UNIVARIADOS DE SEGUIMIENTO =================\n")
================= ANOVAS UNIVARIADOS DE SEGUIMIENTO =================
Response bill_length_mm :
Df Sum Sq Mean Sq F value Pr(>F)
species 2 3858.0 1929.01 412.6 < 2.2e-16 ***
Residuals 163 762.1 4.68
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Response bill_depth_mm :
Df Sum Sq Mean Sq F value Pr(>F)
species 2 446.80 223.399 305.55 < 2.2e-16 ***
Residuals 163 119.18 0.731
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Response flipper_length_mm :
Df Sum Sq Mean Sq F value Pr(>F)
species 2 28412.1 14206.0 375.28 < 2.2e-16 ***
Residuals 163 6170.2 37.9
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Response body_mass_g :
Df Sum Sq Mean Sq F value Pr(>F)
species 2 82687143 41343572 363.83 < 2.2e-16 ***
Residuals 163 18522303 113634
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
El análisis MANOVA revela la existencia de diferencias morfológicas multivariadas altamente significativas entre las tres especies de pingüinos, un patrón que se mantiene constante tanto en la población de hembras como en la de machos. Utilizando la Traza de Pillai —el estadístico recomendado y más robusto frente a la heterogeneidad de covarianzas previamente detectada— confirmamos que el factor especie tiene un efecto determinante sobre el conjunto de características físicas. Tanto en las hembras (Pillai = 1.63, F = 175.46, p < 0.001) como en los machos (Pillai = 1.73, F = 255.59, p < 0.001), los valores de la traza se acercan fuertemente al máximo teórico de 2. Esto indica que la especie explica una inmensa proporción de la varianza total del modelo, logrando una separación casi perfecta de los grupos, lo cual es reafirmado por valores de Wilks extremadamente cercanos a cero en ambos sexos.
Por su parte, los ANOVAs univariados de seguimiento demuestran que esta contundente separación multivariada no es impulsada por una sola característica aislada, sino que las cuatro variables biométricas difieren significativamente entre las especies (p < 0.001 en todos los casos). No obstante, el poder de discriminación de cada rasgo varía ligeramente según el dimorfismo de cada sexo. En las hembras, la longitud de la aleta (F = 418.15) y la masa corporal (F = 391.82) son los atributos que marcan la mayor diferencia entre las especies. En contraste, en la población de machos, es la longitud del pico (F = 412.60) la característica que lidera la separación anatómica, seguida de cerca por la longitud de la aleta (F = 375.28).
Código
library(MASS)library(ggplot2)library(dplyr)# 1. Calculo de funciones discriminantes canonicas por sexolda_h <-lda(species ~ bill_length_mm + bill_depth_mm + flipper_length_mm + body_mass_g, data = datos_limpios_h)lda_m <-lda(species ~ bill_length_mm + bill_depth_mm + flipper_length_mm + body_mass_g, data = datos_limpios_m)# 2. Proyeccion de las observaciones en los ejes canonicos (LD1 y LD2)df_cda_h <-data.frame(species = datos_limpios_h$species, sex ="Hembras", predict(lda_h)$x)df_cda_m <-data.frame(species = datos_limpios_m$species, sex ="Machos", predict(lda_m)$x)df_cda_total <-rbind(df_cda_h, df_cda_m)# 3. Grafico de dispersion canonica con elipses de confianza al 95%ggplot(df_cda_total, aes(x = LD1, y = LD2, color = species, fill = species)) +geom_point(alpha =0.5, size =2.5) +stat_ellipse(geom ="polygon", alpha =0.15, level =0.95, linewidth =0.8) +facet_wrap(~ sex) +scale_color_manual(values =c("Adelie"="#FF8C00", "Chinstrap"="#A020F0", "Gentoo"="#008B8B")) +scale_fill_manual(values =c("Adelie"="#FF8C00", "Chinstrap"="#A020F0", "Gentoo"="#008B8B")) +labs(title ="Proyección de Especies en el Espacio Canónico del MANOVA",subtitle ="Separación clara entre centroides multivariados (Elipses de confianza al 95%)",x ="Primera Dimensión Canónica (LD1)",y ="Segunda Dimensión Canónica (LD2)",color ="Especie", fill ="Especie") +theme_minimal() +theme(legend.position ="bottom",strip.text =element_text(face ="bold", size =11))