1 Análisis de la base de datos iris

2 Abstract:

La base de datos iris es un conjunto clásico en estadística y aprendizaje automático. Fue introducida por R. A. Fisher en 1936 para estudiar hasta qué punto mediciones morfológicas (longitud y ancho de sépalo y de pétalo) permiten diferenciar tres especies de Iris: iris setosa, iris versicolor e iris virginica (Fisher, 1936; UCI Machine Learning Repository, 2025; scikit-learn developers, 2025). Esta base contiene 150 observaciones totales (50 por especie), con cuatro variables cuantitativas continuas medidas en centímetros y una variable categórica de especie. Este trabajo aplica estadística descriptiva, visualización exploratoria e inferencia básica (pruebas de normalidad) en R sobre iris, con dos objetivos: (1) describir los patrones de tamaño y forma floral entre especies y (2) evaluar qué variables aportan mayor poder de separación entre especies. La literatura y recursos didácticos recientes muestran que las dimensiones del pétalo (Petal.Length y Petal.Width) son las más discriminantes entre las especies y que, en particular, I. setosa es casi perfectamente separable de las otras dos especies usando solo esas variables (Fisher, 1936; scikit-learn developers, 2025; Explore Code, 2022).

2.1 Objetivo del trabajo:

El objetivo es usar R y el ecosistema tidyverse para llevar a cabo análisis exploratorio de datos (EDA), cálculo de estadísticos descriptivos básicos (media, mediana, rango, desviación estándar), visualización (histogramas y boxplots) y pruebas de normalidad en el conjunto iris. Este enfoque refleja el uso tradicional de iris como dataset de referencia para ilustrar clasificación supervisada, análisis multivariante y validación de modelos, debido a que las tres clases están balanceadas (50 observaciones cada una) y las variables son continuas y fácilmente interpretables en términos biológicos (UCI Machine Learning Repository, 2025; scikit-learn developers, 2025; Explore Code, 2022).

3 Exploración inicial de la base de datos:

La base iris contiene 150 filas (plantas) y cinco columnas relevantes para el análisis: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width (todas cuantitativas continuas en cm) y Species (factor con tres niveles). Al examinar los primeros y últimos registros (Tabla 1), se observa que I. setosa presenta pétalos muy cortos y estrechos (por ejemplo ~1.4 cm de largo y ~0.2 cm de ancho), mientras que I. virginica exhibe pétalos considerablemente más largos y anchos (hasta ~6.9 cm de largo y ~2.5 cm de ancho), lo que anticipa una clara diferenciación morfológica entre especies (Wikipedia contributors, 2025; scikit-learn developers, 2025; Explore Code, 2022).

#10 primeros datos
    primeros <- iris %>% 
      slice_head(n = 10) %>% 
        mutate(N = 1:10) %>% #Creamos una nueva columna N que enumera las filas del 1 al 10
          select(N, everything()) #Movemos la columna N al inicio de la tabla
    
    #10 últimos datos
    ultimos <- iris %>% 
      slice_tail(n = 10) %>% 
        mutate(N = 141:150) %>% 
          select(N, everything())

    #Unimos los datos en una sola tabla
    data <- rbind(primeros, ultimos)

    #Mostramos la tabla usando kable(data, caption)
    kable(data, caption = "Tabla 1: 10 primeros y 10 últimos datos del conjunto iris") %>%
      kable_styling(full_width = FALSE, position = "center", bootstrap_options = c("striped", "bordered"))
Tabla 1: 10 primeros y 10 últimos datos del conjunto iris
N Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 5.0 3.4 1.5 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa
141 6.7 3.1 5.6 2.4 virginica
142 6.9 3.1 5.1 2.3 virginica
143 5.8 2.7 5.1 1.9 virginica
144 6.8 3.2 5.9 2.3 virginica
145 6.7 3.3 5.7 2.5 virginica
146 6.7 3.0 5.2 2.3 virginica
147 6.3 2.5 5.0 1.9 virginica
148 6.5 3.0 5.2 2.0 virginica
149 6.2 3.4 5.4 2.3 virginica
150 5.9 3.0 5.1 1.8 virginica

4 Análisis exploratorio de datos

4.1 Descripción general

El conjunto está perfectamente balanceado: 50 observaciones de I. setosa, 50 de I. versicolor y 50 de I. virginica, lo que facilita comparaciones directas entre especies sin necesidad de corregir por tamaños de muestra desiguales (scikit-learn developers, 2025; Explore Code, 2022). Las cuatro variables cuantitativas (largo/ancho de sépalo y largo/ancho de pétalo) describen la morfología floral y la quinta variable (Species) identifica taxonómicamente la planta, lo cual convierte al dataset en un caso típico de problema de clasificación supervisada (Fisher, 1936; UCI Machine Learning Repository, 2025; Explore Code, 2022).

# Calculamos el número de filas (observaciones) y columnas (variables) del conjunto ‘iris’
tabla_dim <- data.frame(
  "Número de datos" = nrow(iris),    # nrow() devuelve el número de filas de un data frame (R Documentation, n.d.).  
  "Número de columnas" = ncol(iris)  # ncol() devuelve el número de columnas de un data frame (R Documentation, n.d.).  
)

# Creamos una tabla en formato HTML/Markdown para mostrar los resultados anteriores
kable(tabla_dim, caption = "Tabla 2: Tamaño del conjunto de datos iris") %>%  
  kable_styling(full_width = FALSE, 
                bootstrap_options = c("striped", "hover", "condensed", "responsive"),  # mejoras visuales con kableExtra (Zhu, 2024).
                position = "center")
Tabla 2: Tamaño del conjunto de datos iris
Número.de.datos Número.de.columnas
150 5
# Creamos otro data frame que describe cada variable del conjunto ‘iris’ para facilitar la interpretación
tabla_vars <- data.frame(
  Variable = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"),
  Descripción = c("Longitud del sépalo (cm)", 
                  "Ancho del sépalo (cm)",
                  "Longitud del pétalo (cm)", 
                  "Ancho del pétalo (cm)", 
                  "Especie")
)

# Mostramos esta tabla con formato de presentación para que sea claro al lector
kable(tabla_vars, caption = "Tabla 3: Variables del conjunto de datos iris") %>%
  kable_styling(full_width = FALSE, 
                bootstrap_options = c("striped", "hover", "condensed", "responsive"), 
                position = "center")
Tabla 3: Variables del conjunto de datos iris
Variable Descripción
Sepal.Length Longitud del sépalo (cm)
Sepal.Width Ancho del sépalo (cm)
Petal.Length Longitud del pétalo (cm)
Petal.Width Ancho del pétalo (cm)
Species Especie

4.2 Análisis descriptivo por variable

# Seleccionamos las columnas que nos interesan: largo y ancho de sépalo y pétalo, y la especie
iris_cuadricula <- iris |> select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)

# Definimos una función llamada tabla_resumen() que recibe un vector x
# y devuelve un data frame con dos columnas: Estadístico (e.g., Min., 1st Qu., Median…) y Valor (numérico de cada estadístico)
# Utilizamos names(summary(x)) para capturar los nombres de los estadísticos que genera summary(), y as.numeric(summary(x))
# para convertir los valores a formato numérico (útil para luego tabular).
tabla_resumen <- function(x) {
  data.frame(
    Estadístico = names(summary(x)),     # summary() devuelve resumen de vectores/datos (GeeksforGeeks, 2025)
    Valor = as.numeric(summary(x))       # convertimos a numérico para facilidad de presentación
  )
}

# Para cada una de las variables cuantitativas, creamos un "grob" de tabla con tableGrob(),
# luego lo envuelvo en arrangeGrob() para añadir un título (“top”) y preparar los cuatro cuadros en una cuadrícula.
c1 <- arrangeGrob(tableGrob(tabla_resumen(iris_cuadricula$Sepal.Length)),   top = "Sepal.Length")  
c2 <- arrangeGrob(tableGrob(tabla_resumen(iris_cuadricula$Sepal.Width)),    top = "Sepal.Width")  
c3 <- arrangeGrob(tableGrob(tabla_resumen(iris_cuadricula$Petal.Length)),   top = "Petal.Length")  
c4 <- arrangeGrob(tableGrob(tabla_resumen(iris_cuadricula$Petal.Width)),    top = "Petal.Width")  

# Finalmente, usamos grid.arrange() para dibujar los cuatro grobs en una cuadrícula de 2 columnas.
# Esto permite visualizar al mismo tiempo los resúmenes de las cuatro variables cuantitativas.
grid.arrange(c1, c2, c3, c4,
             ncol = 2,
             top = "Tabla 4: Resumen estadístico de las variables del conjunto iris")  # grid.arrange facilita combinar múltiples grobs (gridExtra, 2019)

En la Tabla 4 se resumen estadísticas como mínimo, máximo, media, mediana, IQR y desviación estándar. Sepal.Length tiene una media cercana a 5.84 cm y una mediana de ~5.8 cm, con un rango aproximado de 4.3 a 7.9 cm y una desviación estándar moderada (~0.83 cm), lo cual sugiere una distribución relativamente centrada y sin dispersión extrema. En Sepal.Width la media (~3.06 cm) es ligeramente superior a la mediana (~3.0 cm), el rango va de 2.0 a 4.4 cm y la desviación estándar es más baja (~0.43 cm). Las variables de pétalo muestran más heterogeneidad: Petal.Length tiene una media cercana a 3.76 cm, una desviación estándar alta (~1.76 cm) y su asimetría sugiere que no se distribuye de manera simétrica (scikit-learn developers, 2025; Explore Code, 2022). Petal.Width presenta análoga situación de dispersión alta y asimetría. En resumen, los sépalos muestran variación moderada, mientras que los pétalos muestran alta variabilidad y posibles subgrupos; esto coincide con que las medidas de pétalo capturan diferencias taxonómicas. Esto ha sido mostrado en tutoriales visuales que destacan claramente la separación basada en pétalo (Explore Code, 2022).

4.3 Análisis Graficas Descriptivas Histograma, Boxplot

# Histograma de Sepal.Length  
p1 <- ggplot(iris, aes(x = Sepal.Length)) +  
  geom_histogram(binwidth = 0.2, fill = "skyblue", color = "black") +  # geom_histogram() divide los datos en “bins” y traza barras según frecuencia (Wickham et al., 2025)  
  labs(title = "Histograma de Sepal Length", x = "Sepal Length (cm)", y = "Frecuencia")

# Histograma de Sepal.Width  
p2 <- ggplot(iris, aes(x = Sepal.Width)) +  
  geom_histogram(binwidth = 0.2, fill = "salmon", color = "black") +  
  labs(title = "Histograma de Sepal Width", x = "Sepal Width (cm)", y = "Frecuencia")

# Histograma de Petal.Length  
p3 <- ggplot(iris, aes(x = Petal.Length)) +  
  geom_histogram(binwidth = 0.2, fill = "lightgreen", color = "black") +  
  labs(title = "Histograma de Petal Length", x = "Petal Length (cm)", y = "Frecuencia")

# Histograma de Petal.Width  
p4 <- ggplot(iris, aes(x = Petal.Width)) +  
  geom_histogram(binwidth = 0.2, fill = "plum", color = "black") +  
  labs(title = "Histograma de Petal Width", x = "Petal Width (cm)", y = "Frecuencia")

# Usamos grid.arrange() para disponer los cuatro histogramas en una cuadrícula de 2 columnas, 
# lo cual permite comparar visiblemente la distribución de cada variable simultáneamente (t-redactyl, 2016)  
grid.arrange(p1, p2, p3, p4, ncol = 2)

4.3.1 Histograma

El histograma de Sepal.Length muestra una distribución unimodal con una forma aproximadamente simétrica, con la frecuencia máxima alrededor de 5.5-6.0 cm, alcanzando aproximadamente 15 observaciones en el bin central. La frecuencia disminuye hacia los extremos, desde 4.3 cm hasta 7.9 cm, con una notable reducción en los valores superiores a 7.0 cm, donde las observaciones son escasas. Esto se alinea con la media de 5.843 cm, cercana a la mediana de 5.8 cm, y el rango total de 4.3 a 7.9 cm, indicando una dispersión moderada.

El histograma de Sepal.Width presenta una distribución unimodal con un pico máximo alrededor de 3.0 cm, con una frecuencia superior a 30 observaciones. Las frecuencias disminuyen de manera más pronunciada hacia 2.0 cm y menos abruptamente hacia 4.4 cm, con un rango total de 2.0 a 4.4 cm. La media de 3.057 cm excede ligeramente la mediana de 3.0 cm, lo que indica una leve asimetría hacia la derecha, con la mayoría de las observaciones concentradas en el rango central. El histograma de Petal.Length muestra una distribución con una concentración notable de observaciones entre 1.0 y 2.0 cm, alcanzando frecuencias de 20-25, seguida de una disminución hacia 3.0 cm y un aumento hacia 4.0-5.0 cm, con el rango extendiéndose hasta 6.9 cm. La media de 3.758 cm es menor que la mediana de 4.35 cm, indicando una asimetría hacia la izquierda, con una mayor densidad de datos en los valores inferiores.

El histograma de Petal.Width exhibe una concentración alta entre 0.1 y 0.5 cm, con frecuencias superiores a 40 observaciones, seguida de una disminución hacia 1.0 cm y un aumento gradual hasta 2.5 cm, con frecuencias de 20-30 en el rango superior. La media de 1.199 cm es menor que la mediana de 1.3 cm, indicando una asimetría hacia la izquierda, con la mayor parte de las observaciones agrupadas en los valores más bajos.

# Boxplot de Sepal.Length  
p1 <- ggplot(iris, aes(x = "", y = Sepal.Length)) +  
  geom_boxplot(fill = "skyblue", color = "black") +  # geom_boxplot() representa la distribución de una variable continua y permite identificar mediana, cuartiles y posibles outliers (ggplot2 Team, 2025; GeeksforGeeks, 2025)  
  labs(title = "Boxplot de Sepal Length", x = "", y = "Sepal Length (cm)")

# Boxplot de Sepal.Width  
p2 <- ggplot(iris, aes(x = "", y = Sepal.Width)) +  
  geom_boxplot(fill = "salmon", color = "black") +  
  labs(title = "Boxplot de Sepal Width", x = "", y = "Sepal Width (cm)")

# Boxplot de Petal.Length  
p3 <- ggplot(iris, aes(x = "", y = Petal.Length)) +  
  geom_boxplot(fill = "lightgreen", color = "black") +  
  labs(title = "Boxplot de Petal Length", x = "", y = "Petal Length (cm)")

# Boxplot de Petal.Width  
p4 <- ggplot(iris, aes(x = "", y = Petal.Width)) +  
  geom_boxplot(fill = "plum", color = "black") +  
  labs(title = "Boxplot de Petal Width", x = "", y = "Petal Width (cm)")

# grid.arrange() permite agrupar múltiples objetos gráficos en una cuadrícula para facilitar la comparación visual (R-Graph Gallery, 2025)  
grid.arrange(p1, p2, p3, p4, ncol = 2)

4.3.2 Boxplot

El boxplot de Sepal.Length muestra una mediana aproximada de 5.8 cm, con un rango que abarca desde 4.5 cm hasta 6.4 cm, indicando una distribución moderada. No se observan outliers claros, aunque la distribución sugiere una concentración central.

El boxplot de Sepal.Width presenta una mediana alrededor de 3.0 cm, con un rango que va desde 2.0 cm hasta 3.4 cm, mostrando una distribución relativamente compacta. Se observan algunos outliers bajos cerca de 2.0 cm y uno alto cerca de 4.4 cm.

El boxplot de Petal.Length tiene una mediana aproximada de 4.4 cm, con un rango que va desde 1.6 cm hasta 5.9 cm, lo que indica una dispersión significativa. Se observan outliers bajos cerca de 1.0 cm y un rango amplio que sugiere variabilidad.

El boxplot de Petal.Width muestra una mediana alrededor de 1.3 cm, con un rango que va desde 0.3 cm hasta 2.2 cm, reflejando una dispersión notable. Se identifican outliers bajos cerca de 0.1 cm y uno alto cerca de 2.5 cm, indicando extremos bien definidos.

5 Análisis por especie

5.1 Iris setosa

En Iris setosa, las medidas de sépalo y pétalo presentan baja dispersión y una distribución homogénea. En Sepal.Length, la media es de 5.006 cm y la mediana de 5.0 cm, con una desviación estándar de 0.35 cm, lo que indica una distribución estable y centrada. En Sepal.Width, la media (3.428 cm) y la mediana (3.4 cm) son cercanas, con una desviación estándar de 0.38 cm, reflejando variación moderada dentro de límites estrechos. En Petal.Length, la media (1.462 cm) y la mediana (1.5 cm) se encuentran próximas, con una desviación estándar de 0.17 cm, lo que evidencia uniformidad. Finalmente, Petal.Width presenta una media de 0.246 cm y una mediana de 0.2 cm, con una desviación estándar de 0.10 cm, lo que confirma la baja variabilidad en el ancho del pétalo. En conjunto, las variables de esta especie muestran valores reducidos y consistentes, reflejando una morfología compacta con poca variación entre individuos.

# Filtramos el conjunto para quedarse solo con la especie “setosa” del dataset iris
setosa <- iris %>% 
  filter(Species == "setosa")  # filter() selecciona filas según una condición; parte del paquete {dplyr} (Data Carpentry, 2017).

# Definimos un vector con los nombres de las variables cuantitativas que analizaremos
variables <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")

# Creamos un data frame que contiene para ‘setosa’ la media (mean), mediana (median) y desviación estándar (sd)
stats_setosa <- data.frame(
  Media = sapply(setosa[, variables], mean),             # mean(): calcula el promedio de un vector numérico
  Mediana = sapply(setosa[, variables], median),         # median(): calcula la mediana de un vector numérico
  Desviacion_Estandar = sapply(setosa[, variables], sd)  # sd(): calcula la desviación estándar de un vector numérico
)

# Generamos una tabla con formato presentable para el informe usando kable y estilizado con kableExtra
kable(stats_setosa, caption = "Tabla 5: Estadísticas descriptivas para *Iris setosa*") %>%
  kable_styling(full_width = FALSE,
                position = "center",
                bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                font_size = 13)
Tabla 5: Estadísticas descriptivas para Iris setosa
Media Mediana Desviacion_Estandar
Sepal.Length 5.006 5.0 0.3524897
Sepal.Width 3.428 3.4 0.3790644
Petal.Length 1.462 1.5 0.1736640
Petal.Width 0.246 0.2 0.1053856

5.2 Iris versicolor

En Iris versicolor, las variables presentan mayor dispersión que en setosa. En Sepal.Length, la media (5.94 cm) y la mediana (5.9 cm) son similares, con una desviación estándar de 0.52 cm. En Sepal.Width, la media (2.77 cm) y la mediana (2.8 cm) muestran poca diferencia, con una desviación estándar de 0.31 cm, indicando estabilidad moderada. En Petal.Length, la media (4.26 cm) y la mediana (4.3 cm) presentan coherencia, con una desviación estándar de 0.47 cm, mientras que en Petal.Width la media (1.33 cm) y la mediana (1.3 cm) mantienen proporción con una desviación estándar de 0.20 cm. La dispersión en las variables de pétalo es superior a la observada en setosa, lo que refleja una transición intermedia entre especies de pétalos pequeños y grandes.

# Filtramos el conjunto para quedarse solo con la especie “versicolor” del dataset iris  
versicolor <- iris %>% 
  filter(Species == "versicolor")  # filter() sirve para seleccionar filas según condiciones usando {dplyr} (StatsAndR, 2023).

# Definimos un vector con los nombres de las variables cuantitativas que vamos a analizar  
variables <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")

# Creamos un data frame que contiene para ‘versicolor’ la media (mean), mediana (median) y desviación estándar (sd) de cada variable  
stats_versicolor <- data.frame(
  Media                = sapply(versicolor[, variables], mean),   # mean(): promedio aritmético de un vector numérico  
  Mediana              = sapply(versicolor[, variables], median), # median(): valor que separa la mitad superior de la mitad inferior  
  Desviacion_Estandar  = sapply(versicolor[, variables], sd)      # sd(): desviación estándar, medida de dispersión (Statology, 2022).
)

# Generamos una tabla con formato presentable para el informe usando kable() y kable_styling()  
kable(stats_versicolor,
      caption = "Tabla 6: Estadísticas descriptivas *Iris versicolor*") %>%
  kable_styling(full_width = FALSE,
                position = "center",
                bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                font_size = 13)
Tabla 6: Estadísticas descriptivas Iris versicolor
Media Mediana Desviacion_Estandar
Sepal.Length 5.936 5.90 0.5161711
Sepal.Width 2.770 2.80 0.3137983
Petal.Length 4.260 4.35 0.4699110
Petal.Width 1.326 1.30 0.1977527

5.3 Iris virginica

En Iris virginica, las medias y medianas son mayores en todas las variables, con un aumento notorio en las dimensiones del pétalo. En Sepal.Length, la media es de 6.59 cm y la mediana de 6.5 cm, con una desviación estándar de 0.64 cm. En Sepal.Width, la media (2.97 cm) y la mediana (3.0 cm) presentan valores próximos y una desviación estándar de 0.32 cm. En Petal.Length, la media (5.55 cm) y la mediana (5.5 cm) muestran correspondencia, con una desviación estándar de 0.55 cm. En Petal.Width, la media (2.03 cm) y la mediana (2.0 cm) son casi equivalentes, con una desviación estándar de 0.27 cm. Las medidas de esta especie exhiben la mayor amplitud de valores dentro del conjunto, con una variabilidad más marcada en las variables del pétalo.

# Filtramos el conjunto para quedarnos sólo con la especie “virginica” del dataset iris  
virginica <- iris %>% 
  filter(Species == "virginica")  # filter() selecciona filas bajo una condición – parte del paquete dplyr (Stats & R, 2020).

# Definimos un vector con los nombres de las variables cuantitativas que vamos a analizar  
variables <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")

# Creamos un data.frame que contiene, para ‘virginica’, la media (mean), mediana (median) y desviación estándar (sd) de cada variable  
stats_virginica <- data.frame(
  Media               = sapply(virginica[, variables], mean),    # mean(): calcula el valor promedio (DataCamp, n.d.; STHDA, n.d.).
  Mediana             = sapply(virginica[, variables], median),  # median(): calcula la mediana – útil cuando la distribución está sesgada (Codecademy, n.d.; STHDA, n.d.).
  Desviacion_Estandar = sapply(virginica[, variables], sd)       # sd(): calcula la desviación estándar – mide variabilidad de los datos (STHDA, n.d.; Stats & R, 2020).
)

# Presentamos el data.frame resultante en una tabla estilizada para informe mediante kable() y kable_styling()
kable(stats_virginica, caption = "Tabla 7: Estadísticas descriptivas para *Iris virginica*") %>%
  kable_styling(full_width = FALSE,
                position = "center",
                bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                font_size = 13)
Tabla 7: Estadísticas descriptivas para Iris virginica
Media Mediana Desviacion_Estandar
Sepal.Length 6.588 6.50 0.6358796
Sepal.Width 2.974 3.00 0.3224966
Petal.Length 5.552 5.55 0.5518947
Petal.Width 2.026 2.00 0.2746501

5.4 Comparación general entre especies

Las tres especies muestran diferencias consistentes en las dimensiones de sépalo y pétalo. iris setosa presenta valores pequeños y homogéneos en todas las variables, caracterizados por baja dispersión. iris versicolor ocupa un rango intermedio en la mayoría de las medidas, con incremento progresivo en las dimensiones del pétalo respecto a setosa. Finalmente, iris virginica presenta los valores más altos y la mayor variabilidad, especialmente en Petal.Length y Petal.Width. Estas diferencias cuantitativas confirman la separación morfológica entre las especies y explican la estructura multimodal observada en las distribuciones globales. Las variables del pétalo son las que presentan mayor capacidad de diferenciación entre grupos, mientras que las del sépalo mantienen valores más estables y con menor variabilidad relativa.

6 Visualización comparativa entre especies

6.1 Boxplot de Petal Width,…

# Boxplot de Sepal.Length por especie: mapeamos la estética fill al factor Species
p1 <- ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
  geom_boxplot(color = "black") +    # geom_boxplot() para comparar la distribución entre grupos (R-Graph Gallery, 2018)
  scale_fill_manual(values = c("setosa" = "skyblue",    # scale_fill_manual() permite definir manualmente los colores para cada nivel del factor (sthda.com, n.d.)
                               "versicolor" = "salmon",
                               "virginica" = "lightgreen")) +
  labs(title = "Boxplot de Sepal Length por Especie", 
       x = "Especie", 
       y = "Sepal Length (cm)") +
  theme(legend.position = "none")   # Eliminamos la leyenda porque los colores ya se interpretan por eje x

# Boxplot de Sepal.Width por especie
p2 <- ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species)) +
  geom_boxplot(color = "black") +
  scale_fill_manual(values = c("setosa" = "skyblue",
                               "versicolor" = "salmon",
                               "virginica" = "lightgreen")) +
  labs(title = "Boxplot de Sepal Width por Especie", x = "Especie", y = "Sepal Width (cm)") +
  theme(legend.position = "none")

# Boxplot de Petal.Length por especie
p3 <- ggplot(iris, aes(x = Species, y = Petal.Length, fill = Species)) +
  geom_boxplot(color = "black") +
  scale_fill_manual(values = c("setosa" = "skyblue",
                               "versicolor" = "salmon",
                               "virginica" = "lightgreen")) +
  labs(title = "Boxplot de Petal Length por Especie", x = "Especie", y = "Petal Length (cm)") +
  theme(legend.position = "none")

# Boxplot de Petal.Width por especie
p4 <- ggplot(iris, aes(x = Species, y = Petal.Width, fill = Species)) +
  geom_boxplot(color = "black") +
  scale_fill_manual(values = c("setosa" = "skyblue",
                               "versicolor" = "salmon",
                               "virginica" = "lightgreen")) +
  labs(title = "Boxplot de Petal Width por Especie", x = "Especie", y = "Petal Width (cm)") +
  theme(legend.position = "none")

# grid.arrange() para presentar los cuatro gráficos en una cuadrícula de 2 columnas y comparar visualmente
grid.arrange(p1, p2, p3, p4, ncol = 2)  # (R-Graph Gallery, 2018)

El boxplot de Sepal.Length por especie muestra medianas distintas, con setosa (rojo) presentando una mediana baja de aproximadamente 5.0 cm con un rango compacto de 4.8-5.2 cm y sin outliers, indicando homogeneidad; versicolor (verde) exhibe una mediana intermedia de cerca de 5.9 cm con un rango de 5.6-6.4 cm y un outlier bajo alrededor de 4.5 cm, sugiriendo variabilidad moderada; y virginica (azul) muestra una mediana alta de aproximadamente 6.5 cm con un rango de 6.2-6.9 cm y un outlier alto cerca de 7.7 cm, reflejando mayor dispersión y valores extremos. Para Sepal.Width, setosa tiene una mediana alrededor de 3.4 cm con un rango de 3.2-3.7 cm y un outlier alto cerca de 4.4 cm, indicando valores más altos y variabilidad; versicolor muestra una mediana de aproximadamente 2.8 cm con un rango de 2.5-3.1 cm y outliers bajos cerca de 2.0 cm, sugiriendo concentración en valores intermedios; virginica presenta una mediana de cerca de 2.9 cm con un rango de 2.7-3.2 cm y un outlier bajo cerca de 2.0 cm, mostrando homogeneidad relativa. En Petal.Length, setosa tiene una mediana baja de aproximadamente 1.5 cm con un rango de 1.3-1.7 cm y outliers bajos cerca de 1.0 cm, indicando uniformidad; versicolor exhibe una mediana intermedia de alrededor 4.3 cm con un rango de 4.0-4.8 cm y un outlier bajo cerca de 3.0 cm, reflejando variabilidad moderada; virginica muestra una mediana alta de aproximadamente 5.6 cm con un rango de 5.1-6.0 cm y outliers bajos cerca de 4.5 cm, sugiriendo mayor dispersión. Finalmente, en Petal.Width, setosa presenta una mediana baja de aproximadamente 0.2 cm con un rango de 0.1-0.3 cm y outliers bajos cerca de 0.1 cm, indicando valores mínimos; versicolor tiene una mediana intermedia de cerca de 1.3 cm con un rango de 1.0-1.5 cm y un outlier bajo cerca de 1.0 cm, mostrando variabilidad; virginica exhibe una mediana alta de aproximadamente 2.0 cm con un rango de 1.7-2.3 cm y un outlier alto cerca de 2.5 cm, reflejando mayor amplitud. Estas diferencias en medianas y rangos entre las variables por especie destacan que Petal.Width y Petal.Length son las más discriminantes, con separaciones claras entre los grupos, mientras que Sepal.Length y Sepal.Width muestran solapamiento, especialmente en versicolor y virginica, aunque setosa se distingue por valores extremos en ambas.

6.1.1 Interpretación y conclusiones del análisis descriptivo del conjunto Iris

El análisis del conjunto Iris permite establecer varias conclusiones relevantes sobre la estructura y las diferencias entre especies. En primer lugar, se evidencia que las variables del pétalo, específicamente Petal.Length y Petal.Width, son las que mejor discriminan entre las tres especies. Los histogramas y boxplots muestran que Iris setosa concentra valores muy bajos, Iris versicolor se ubica en un rango intermedio y Iris virginica presenta las medidas más altas. Este patrón progresivo refleja una clara separación entre grupos, ya que las longitudes y anchos de pétalo son atributos directamente relacionados con la morfología floral y, por tanto, con la diferenciación taxonómica (Fisher, 1936; scikit-learn developers, 2025). En consecuencia, estas variables aportan una alta capacidad predictiva en modelos de clasificación, como los analizados tradicionalmente en aprendizaje automático y análisis multivariado (Explore Code, 2022).

En segundo lugar, las variables de sépalo (Sepal.Length y Sepal.Width) muestran un mayor grado de solapamiento, especialmente entre versicolor y virginica. Los boxplots reflejan medianas cercanas y rangos superpuestos, lo que implica que las medidas del sépalo son menos informativas para distinguir especies. Aunque setosa mantiene valores significativamente menores en ambas dimensiones, la similitud entre las otras dos especies indica que los sépalos son menos determinantes morfológicamente. Esto coincide con el uso clásico del conjunto de datos, en el que las variables del pétalo son preferidas para separar las clases (UCI Machine Learning Repository, 2025).

Por último, la distribución de los datos sugiere que no todas las variables siguen una normalidad estricta, especialmente en las medidas del pétalo, donde los histogramas muestran asimetrías marcadas. Petal.Length y Petal.Width presentan colas alargadas hacia la derecha o la izquierda dependiendo de la especie, lo que implica la presencia de sesgos y posibles subgrupos en los datos. Esto concuerda con estudios que advierten que, aunque las pruebas de normalidad como Shapiro–Wilk o Kolmogorov–Smirnov son útiles, su aplicación debe ser cuidadosa en conjuntos con subpoblaciones (Ghasemi & Zahediasl, 2012; GraphPad Software, 2025). En consecuencia, se recomienda el uso de métodos no paramétricos o transformaciones logarítmicas antes de aplicar análisis estadísticos que asuman normalidad.

7 Prueba de Normalidad

La prueba de normalidad nos ayuda a concluir si los datos siguen una distribución normal, esto nos va a ayudar a entender cómo se comportan las variables de la base de datos. Una distribución normal se caracteriza por su forma de campana de Gauss y ser simétrica, lo que nos indica que la mayoría de los valores se concentran alrededor de la media, los valores extremos son poco frecuentes, y la asimetría (skewness) es cercana a cero. También, la desviación estándar refleja qué tanto se dispersan los datos respecto a la media.

En este proyecto, vamos a verificar la normalidad de las variables Sepal.Length y Petal.Length del conjunto de datos iris, mediante la prueba de Shapiro-Wilk. En un artículo de Sovietas (Revista de Ciencias Sociales Humanísticas de la Universidad de Panamá) del año 2021 se cita a Novales (2010) quien expresa que este test se emplea para contrastar normalidad cuando el tamaño de la muestra es menor a 50 observaciones y en muestras grandes es equivalente al test de Kolmogórov-Smirnov. Sin embargo, la prueba de Kolmogórov–Smirnov es no paramétrica, a diferencia de Shapiro–Wilk, que requiere la media y la desviación estándar de las variables para calcular el resultado, y compara la forma de la distribución acumulativa de los datos con una distribución teórica. Esta prueba exige valores únicos, ya que las repeticiones pueden afectar la diferencia máxima entre las funciones acumulativas y comprometer la validez del resultado, como advierte la guía de GraphPad Prism: “Don’t use the Kolmogorov-Smirnov test if the outcome (Y values) are categorical, with many ties” (GraphPad Prism, s.f.). Si observamos el head y tail de la Tabla 1, existen valores repetidos; por ello, en este estudio se utilizó la prueba de Shapiro–Wilk, que admite valores repetidos y tiene mayor potencia para detectar desviaciones de la normalidad en muestras pequeñas o medianas.

knitr::opts_chunk$set(echo = FALSE)   

#Hacemos la prueba para Sepal.Length
normal_sepal <- shapiro.test(iris$Sepal.Length)

#Petal.Length
normal_petal <- shapiro.test(iris$Petal.Length)
normal_sepal
## 
##  Shapiro-Wilk normality test
## 
## data:  iris$Sepal.Length
## W = 0.97609, p-value = 0.01018
normal_petal
## 
##  Shapiro-Wilk normality test
## 
## data:  iris$Petal.Length
## W = 0.87627, p-value = 7.412e-10
#Ahora, una vez tenemos los resultados, utilizamos condicionales para ver si las variables cumplen con tener una distribución normal

interpretar_normal <- function(resultado, nombre) {
          cat("Variable:", nombre, "\n")
          if (resultado$p.value < 0.05) {
            cat("Los datos NO siguen una distribución normal: p =", resultado$p.value, "< 0.05\n")
          } else {
            cat("Los datos siguen una distribución normal: p =", resultado$p.value, "≥ 0.05\n")
          }
        }

#Y enviamos como argumento los datos de las variables sepal y petal
interpretar_normal(normal_sepal, "Sepal.Length")
## Variable: Sepal.Length 
## Los datos NO siguen una distribución normal: p = 0.01018116 < 0.05
interpretar_normal(normal_petal, "Petal.Length")
## Variable: Petal.Length 
## Los datos NO siguen una distribución normal: p = 7.412263e-10 < 0.05
normal_sepal <- shapiro.test(iris$Sepal.Length)

normal_petal <- shapiro.test(iris$Petal.Length)

tabla_normalidad <- data.frame(
Variable = c("Sepal.Length", "Petal.Length"),
Estadístico_W = c(round(normal_sepal$statistic, 4), round(normal_petal$statistic, 4)),
Valor_p = c(round(normal_sepal$p.value, 4), round(normal_petal$p.value, 4)),
Interpretación = c(
ifelse(normal_sepal$p.value < 0.05, "No sigue distribución normal", "Sigue distribución normal"),
ifelse(normal_petal$p.value < 0.05, "No sigue distribución normal", "Sigue distribución normal")
)
)

kable(tabla_normalidad, caption = "Resultados de la prueba de normalidad Shapiro-Wilk") %>%
kable_styling(full_width = FALSE,
position = "center",
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
font_size = 13)
Resultados de la prueba de normalidad Shapiro-Wilk
Variable Estadístico_W Valor_p Interpretación
Sepal.Length 0.9761 0.0102 No sigue distribución normal
Petal.Length 0.8763 0.0000 No sigue distribución normal

Se utilizó la función shapiro.test() de R, que calcula automáticamente el estadístico W de Shapiro–Wilk y su valor p. Para cada variable pudimos observar si los datos seguían una distribución normal a partir de la condición: si p < 0.05, se rechazaba la normalidad; si p ≥ 0.05, se consideraba que los datos eran normales. Luego, los resultados se resumieron una tabla que incluye el estadístico W, el valor p y el resultado sobre si Sepal.Length y Petal.Length siguen una distribución normal. En esta última vimos que sus valores no se ajustan a una curva de campana e inferimos que se deben considerar métodos estadísticos no paramétricos para análisis/cálculos posteriores.

8 Referencias

Analytics Using R. (2019). 10.2 Data Frame Features. https://pubs.wsb.wisc.edu/academics/analytics-using-r-2019/data-frame-features.html

Appsilon. (2021, November 9). How to Make Stunning Boxplots in R: A Complete Guide to ggplot Boxplot. https://wordpress.appsilon.com/ggplot2-boxplots/

Codecademy. (n.d.). Learn dplyr: Aggregates Cheatsheet. https://www.codecademy.com/learn/learn-dplyr/modules/learn-r-aggregates/cheatsheet

Codecademy. (n.d.). Learn R: Mean, Median, and Mode Cheatsheet. https://www.codecademy.com/learn/learn-r/modules/r-stats-mean-median-mode/cheatsheet

ChatGPT (GPT-5). (2025). Asistencia en la mejora de redacción, estructuración académica y referencias APA 7 para el análisis estadístico y visualización del conjunto de datos Iris en R. OpenAI.

CRAN gridExtra. (2019). Laying out multiple plots on a page. https://cran.r-project.org/web/packages/egg/vignettes/Ecosystem.html

Data Carpentry contributors. (2017). Aggregating and analyzing data with dplyr. https://datacarpentry.github.io/R-genomics/04-dplyr.html

DataCamp. (n.d.). Descriptive Statistics in R. https://www.datacamp.com/doc/r/descriptives

DataCamp. (2022). How to Make a Histogram with ggplot2. https://www.datacamp.com/tutorial/make-histogram-ggplot2

Explore Code. (2022). Exploratory Data Analysis on Iris Dataset – 1: Understanding the Data and 1-d Scatter Plot Analysis [Video]. YouTube. https://www.youtube.com/watch?v=aO6gG0vugcc

Explore Code. (2022). Exploratory Data Analysis on Iris Dataset – 2: 2-D Scatter Plot Analysis [Video]. YouTube. https://www.youtube.com/watch?v=lENglMDTnIw

Explore Code. (2022). Exploratory Data Analysis on Iris Dataset – 3: 3-D Analysis [Video]. YouTube. https://www.youtube.com/watch?v=3Lxj8CziuHs

Fisher, R. A. (1936). The use of multiple measurements in taxonomic problems. Annals of Eugenics, 7(2), 179–188.

Flores Tapia, C. E., & Flores Cevallos, K. L. (2021). Pruebas para comprobar la normalidad de datos en procesos productivos: Anderson-Darling, Ryan-Joiner, Shapiro-Wilk y Kolmogórov-Smirnov. Societas. Revista de Ciencias Sociales y Humanísticas, 23(2), 1–15. https://portal.amelica.org/ameli/jatsRepo/341/3412237018/3412237018.pdf

GeeksforGeeks. (2025, July 15). Box plot in R using ggplot2. https://www.geeksforgeeks.org/r-language/box-plot-in-r-using-ggplot2/

GeeksforGeeks. (2025, July 23). How to use summary() Function in R? https://www.geeksforgeeks.org/r-language/how-to-use-summary-function-in-r/

GeeksforGeeks. (2025, July 25). Compute Summary Statistics in R. https://www.geeksforgeeks.org/compute-summary-statistics-in-r/

Ghasemi, A., & Zahediasl, S. (2012). Normality tests for statistical analysis: A guide for non-statisticians. International Journal of Endocrinology and Metabolism, 10(2), 486–489. https://doi.org/10.5812/ijem.3505

GraphPad Prism. (s.f.). Interpreting results: Kolmogorov–Smirnov test. GraphPad Prism 10 Statistics Guide. https://www.graphpad.com/guides/prism/latest/statistics/interpreting_results_kolmogorov-smirnov_test.htm

GraphPad Software. (2025). Q & A: Normality tests. GraphPad Prism Statistics Guide. https://www.graphpad.com/support/faqid/959/

Hostman. (2025, January 29). How to find standard deviation in R using simple functions and grouped data. https://hostman.com/tutorials/how-to-find-standard-deviation-in-r/

Introduction to R. (n.d.). 3.5 Summarising data frames. https://intro2r.com/summarising-data-frames.html

Map color/fill scales. (n.d.). Specifying fill colour independent of mapping aesthetics in boxplot (R, ggplot). Stack Overflow. https://stackoverflow.com/questions/72145589/specifying-fill-color-independent-of-mapping-aesthetics-in-boxplot-r-ggplot

R-Coder. (n.d.). Number of rows and columns in R [nrow(), ncol() and dim …]. https://r-coder.com/nrow-ncol-dim-r/

R Documentation. (n.d.). arrangeGrob: arrangeGrob. https://www.rdocumentation.org/packages/gridExtra/versions/0.8.5/topics/arrangeGrob

R Documentation. (n.d.). nrow: The Number of Rows/Columns of an Array. https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/nrow

R-Graph Gallery. (2018). Boxplots in ggplot2. https://r-graph-gallery.com/boxplot.html

R-Graph Gallery. (2025). Basic histogram with ggplot2. https://r-graph-gallery.com/220-basic-ggplot2-histogram.html

R-Graph Gallery. (2025). Boxplot: The most basic boxplot you do using ggplot2. https://r-graph-gallery.com/boxplot.html

R-Tutor. (n.d.). Data Frame | R Tutorial. https://www.r-tutor.com/r-introduction/data-frame

Scale_fill_manual & Other scales. (n.d.). ggplot2 box plot: Quick start guide (R software and data visualization). https://www.sthda.com/english/wiki/ggplot2-box-plot-quick-start-guide-r-software-and-data-visualization

scikit-learn developers. (2025). Iris plants dataset. In scikit-learn User Guide (Version 1.7.2).

Statology. (2022, September 2). How to calculate standard deviation using dplyr (with examples). https://www.statology.org/dplyr-standard-deviation/

Stats & R. (2020, January 22). Descriptive statistics in R. https://statsandr.com/blog/descriptive-statistics-in-r/

StatsAndR. (2023, November 27). Introduction to data manipulation in R with {dplyr}. https://statsandr.com/blog/introduction-to-data-manipulation-in-r-with-dplyr/

STHDA. (n.d.). Descriptive Statistics and Graphics. https://www.sthda.com/english/wiki/descriptive-statistics-and-graphics

t-redactyl. (2016). Creating plots in R using ggplot2 – Part 7: histograms. https://t-redactyl.github.io/blog/2016/02/creating-plots-in-r-using-ggplot2-part-7-histograms.html

UCI Machine Learning Repository. (2025). iris [Data set]. UCI Machine Learning Repository.

Wikipedia contributors. (2025, February 15). Iris flower data set. In Wikipedia, The Free Encyclopedia. https://en.wikipedia.org/wiki/Iris_flower_data_set

Wickham, H., & Grolemund, G. (2019). R for Data Science. O’Reilly Media.

Wickham, H., et al. (2025). Geom_histogram: Visualise the distribution of a single continuous variable. ggplot2 Reference. https://ggplot2.tidyverse.org/reference/geom_histogram.html

Xie, Y. (n.d.). 10.1 The function knitr::kable() | R Markdown Cookbook. https://bookdown.org/yihui/rmarkdown-cookbook/kable.html

Zhu, H. (2024). 10.2 The kableExtra package | R Markdown Cookbook. https://bookdown.org/yihui/rmarkdown-cookbook/kableextra.html