De toy datasets a mini-proyecto de investigación con R


De toy datasets a mini-proyecto de investigación con R

Objetivos de aprendizaje

  1. Descubrir y cargar toy datasets integrados en R y en paquetes populares.
  2. Explorar y resumir variables clave con funciones base y tidyverse.
  3. Plantear una pregunta de investigación clara y viable con datos de juguete.
  4. Diseñar un flujo de trabajo reproducible desde la exploración hasta la visualización.
  5. Comunicar hallazgos en un breve informe R Markdown.

Índice de contenidos

1. Introducción a los toy datasets en R
2. Selección del dataset y planteamiento del problema
3. Exploración inicial y limpieza mínima
4. Análisis descriptivo guiado
5. Visualización rápida con ggplot2
6. De la pregunta a la mini-investigación

1. Introducción a los toy datasets en R

1.1 ¿Qué es un toy dataset y por qué usarlo?

Un toy dataset (conjunto de datos “de juguete”) es un conjunto pequeño, limpio y bien documentado que viene incluido en R base o en paquetes muy difundidos. Está pensado para practicar funciones, demostrar conceptos estadísticos y construir ejemplos reproducibles sin la sobrecarga de data wrangling complejo. En esencia, son “arenas de juego” seguras donde puedes:

  • Aprender sintaxis sin preocuparte de permisos, licencias o tamaños gigantes.
  • Probar modelos de manera rápida antes de aplicarlos a datos reales más ruidosos.
  • Compartir código reproducible: cualquier persona con R puede ejecutar el mismo script y obtener idénticos resultados.
  • Enseñar estadística o programación sin exponer datos sensibles.
  • Comparar métodos (base R vs. tidyverse, etc.) en igualdad de condiciones.

En clase: Usaremos toy datasets para construir un pipeline completo —desde la exploración hasta la visualización— y luego extrapolaremos la metodología a proyectos con datos reales.

Un pipeline es una secuencia ordenada de pasos que automatiza el recorrido de los datos desde que se cargan hasta que se presentan los resultados. Cada etapa —limpieza, transformación, análisis y visualización— toma la salida de la fase anterior y la usa como entrada, de modo que el flujo avanza sin intervención manual repetitiva. Esto garantiza reproducibilidad (cualquier persona puede volver a ejecutar todo el proceso y obtener los mismos resultados) y eficiencia (las tareas se encadenan de forma clara y lógica, evitando errores de “copiar-pegar” o trabajos duplicados).


1.2 Principales fuentes integradas (datasets, palmerpenguins, gapminder, etc.)

A continuación se listan los paquetes más populares que distribuyen toy datasets de acceso inmediato, junto con un vistazo rápido a su contenido principal y una línea de código para cargarlos.

Paquete / DatasetTamaño (filas × variables)TemáticaCarga rápida
R base – datasets≈ 20+ datasets
(iris 5×150, mtcars 11×32…)
Botánica, automóviles, series temporalesdata(iris)
palmerpenguinspenguins344 × 8Mediciones morfológicas de pingüinos en la Antárticalibrary(palmerpenguins)
data(penguins)
gapmindergapminder1 704 × 6Indicadores socio-económicos (1952-2007)library(gapminder)
data(gapminder)
nycflights13flights336 776 × 19Vuelos que salen de NYC en 2013library(nycflights13)
babynamesbabynames≈ 1,9 M × 5Nombres de bebés en EE. UU. (1880-2022)library(babynames)

Para descubrir qué datasets incluye cualquier paquete, basta con inspeccionar su documentación:

library(help = "datasets")      # lista todo lo integrado en R base
data(package = "palmerpenguins")# lista datasets del paquete indicado

En las siguientes secciones elegiremos uno de estos conjuntos, formularemos una pregunta de investigación y recorreremos todo el flujo analítico hasta generar un mini-informe reproducible.

2. Selección del dataset y planteamiento del problema

2.1 Criterios de selección: tamaño, temática y variables

Antes de lanzarte a programar conviene detenerte y elegir cuidadosamente el toy dataset que usarás. Un buen punto de partida asegura que el resto del flujo (el pipeline) sea fluido y que las conclusiones tengan sentido. A continuación se resumen los criterios prácticos más importantes:

CriterioPreguntas guíaConsejo rápido
Tamaño (n filas × variables)¿Puedes examinar las primeras filas a simple vista?
¿Tarda más de 1 s en cargarse?
Para ejercicios de aula, busca < 10 000 filas y < 50 columnas.
Temática o contexto¿Te resulta interesante o relevante?
¿Hay un público que valore los hallazgos?
Elige un tema que motive: ecología (pingüinos), salud, economía, etc.
Variable objetivo¿Tienes claro qué variable quieres explicar, comparar o predecir?
¿Es numérica o categórica?
Asegúrate de que exista al menos una variable dependiente claramente definida.
Calidad y documentación¿Incluye ?dataset_name con descripción completa?
¿Conoces la unidad de medida y las categorías?
Prefiere datasets bien documentados para evitar supuestos dudosos.
Variedad de tipos¿Contiene algo de “todo”: numérico, categórico, fechas?
¿Permite practicar filtros, tablas y gráficos distintos?
Cuanto más heterogéneo, más rico para ejercitar distintas funciones.
Ausencia de valores perdidos¿La columna clave tiene muchos NA?
¿Necesitarás limpieza pesada?
En un toy dataset conviene minimizar la fase de limpieza para centrarse en el análisis.

Si un conjunto cumple la mayoría de estos criterios, lo más probable es que puedas ir del “hello world” al informe final en una sola sesión de trabajo.


2.2 Ejemplos de preguntas de investigación “pequeñas pero potentes”

La clave de un mini-proyecto exitoso no es la complejidad, sino la claridad. Tu pregunta debe ser lo bastante concreta para responderla en unas cuantas líneas de código, pero lo bastante interesante para contar una historia. Aquí van ideas listas para usar o adaptar:

DatasetPregunta sugeridaTipo de análisis
iris¿Qué especie muestra mayor variabilidad en el largo del sépalo?Descriptivo + boxplot
palmerpenguins::penguins¿Difieren significativamente los pesos medios entre Adélie y Gentoo?t-test + violín plot
gapminder¿Cómo cambió la esperanza de vida en Latinoamérica entre 1952 y 2007?Línea temporal + resumen por año
mtcars¿Los autos con transmisión automática consumen más combustible que los manuales?Gráfico de densidad + prueba U de Mann-Whitney
nycflights13::flights¿Cuál de los tres aeropuertos de NYC presenta el mayor retraso promedio en enero?Filtrado + tabla de medias

Observa que cada pregunta cumple tres requisitos básicos:

  1. Alcance limitado: una o dos variables principales.
  2. Acción clara: comparar, describir o correlacionar.
  3. Resultado interpretable: la respuesta cabe en un par de frases y un gráfico.

Tu turno: Elige un dataset, revisa sus variables con str() y formula tu propia pregunta en una sola línea. Ese será el eje de tu mini-proyecto.

3. Exploración inicial y limpieza mínima

3.1 Inspección de estructura con str() y skimr::skim()

El primer paso de cualquier pipeline es mirar los datos: confirmar cuántas filas y columnas hay, qué tipos de variable existen y si aparecen NA. Dos funciones cubren la mayoría de necesidades iniciales:

FunciónQué muestraCuándo usarla
str()Clase del objeto, número de filas, tipo y muestra de cada columna.Exploración rápida en cualquier instalación base de R.
skimr::skim()Resumen extendido: missing, media, p50, p99, long/short strings…Diagnóstico completo que evita calcular summary() por separado.

Ejemplo con palmerpenguins::penguins

# Cargar paquetes
library(palmerpenguins)   # datos
library(skimr)            # resumen extendido
# 1. Vista estructural rápida
str(penguins)
# 2. Resumen extendido
skim(penguins)

La salida de str() revela, por ejemplo, que species y sex son factores con varios NA, mientras que bill_length_mm es numérica. Con skim() verás de inmediato valores faltantes y estadísticas útiles como cuartiles y número de categorías únicas.


3.2 Tratamiento rápido de valores faltantes y tipos de datos

Los toy datasets ya vienen bastante limpios, pero casi siempre verás algo de NA o columnas mal tipadas (por ejemplo, años como números cuando conviene factor). La estrategia exprés consiste en:

  1. Detectar NA por variable.
  2. Eliminar o imputar solo si son pocos y no arruinan la muestra.
  3. Corregir tipos con as.factor(), as.numeric(), etc.

1 • Localizar los NA

# Conteo de NA por columna
colSums(is.na(penguins))

2 • Decidir: ¿quitar filas o imputar?

Para un análisis exploratorio breve es aceptable eliminar filas con valores faltantes en las variables clave:

library(dplyr)
penguins_clean <- penguins %>% 
  tidyr::drop_na(bill_length_mm, bill_depth_mm, sex)

Si el porcentaje de NA supera ~10 % en una variable importante, sustitúyelos por un valor “seguro” (media, mediana o categoría “Desconocido”):

# Reemplazar NA en 'sex' por "unknown"
penguins$sex <- forcats::fct_explicit_na(penguins$sex, na_level = "unknown")

3 • Ajustar tipos de datos

Cuando la variable representa un grupo finito (año de estudio, isla, transmisión), conviene usar factor; cuando sea código ID, conviértelo a character para evitar promedios absurdos.

SituaciónCódigo de correcciónMotivo
Año que actúa como categoríapenguins$year <- as.factor(penguins$year)Permite facetas y barras por año sin orden numérico engañoso.
Columna numérica leída como textodf$ingreso <- as.numeric(df$ingreso)Habilita cálculos de media y desviación estándar.
ID con ceros a la izquierdadf$id <- as.character(df$id)Evita que “0012” se convierta en 12.

Ejemplo completo de limpieza mínima

penguins_min <- penguins %>% 
  # 1. Conservar solo variables clave
  select(species, island, sex, bill_length_mm, body_mass_g) %>% 
  
  # 2. Eliminar filas con NA en variables numéricas
  drop_na(bill_length_mm, body_mass_g) %>% 
  
  # 3. Reetiquetar NA en 'sex'
  mutate(sex = forcats::fct_explicit_na(sex, na_level = "unknown")) %>% 
  
  # 4. Asegurar que 'island' sea factor ordenado alfabéticamente
  mutate(island = factor(island, levels = sort(unique(island))))

Después de esta limpieza mínima el dataset queda listo para describir, modelar o visualizar sin interferencias de NA ni tipos inconsistentes. El objetivo no es perfeccionar cada celda, sino despejar rápidamente los obstáculos que impedirían avanzar al análisis.

4. Análisis descriptivo guiado

4.1 Tablas de frecuencia y medidas de tendencia central

Con el dataset ya depurado llega el momento de responder la primera batería de preguntas descriptivas: ¿Qué tan frecuente es cada categoría? y ¿Dónde se concentra la distribución de las variables numéricas?

4.1.1 Frecuencias con table() y dplyr::count()

library(dplyr)
# Frecuencia absoluta de especies
freq_species <- table(penguins_min$species)
freq_species
# La misma operación, versión tidy
penguins_min %>%
  count(species, name = "n") %>%
  mutate(pct = round(n / sum(n) * 100, 1))
speciesn%
Adelie15244.9
Chinstrap6820.1
Gentoo11935.0

A simple vista se aprecia que Adelie es la especie dominante (~45 %), mientras que Chinstrap es la menos representada. Esta tabla de dos columnas (n y %) suele bastar para el informe final.

4.1.2 Tendencia central para variables numéricas

Las medidas de tendencia central más habituales se obtienen con mean() y median(). Para tablas múltiples usaremos dplyr::summarise().

penguins_min %>%
  summarise(
    n              = n(),
    bill_mean_mm   = mean(bill_length_mm, na.rm = TRUE),
    bill_median_mm = median(bill_length_mm, na.rm = TRUE),
    mass_mean_g    = mean(body_mass_g, na.rm = TRUE),
    mass_median_g  = median(body_mass_g, na.rm = TRUE)
  )
nbill_mean_mmbill_median_mmmass_mean_gmass_median_g
33943.944.542014050

Observa la ligera diferencia entre media (43.9 mm) y mediana (44.5 mm) para bill_length_mm; su cercanía indica que no existen valores extremos exagerados en esta variable.


4.2 Comparaciones básicas entre grupos con dplyr

Después del paneo general viene la comparación: ¿cambia el patrón según especie, sexo o isla? Gracias a dplyr podemos agrupar y resumir en una sola línea.

4.2.1 Media y mediana por especie

penguins_min %>%
  group_by(species) %>%
  summarise(
    count     = n(),
    bill_avg  = round(mean(bill_length_mm), 1),
    mass_med  = median(body_mass_g)
  )
speciescountbill_avg (mm)mass_med (g)
Adelie15238.83700
Chinstrap 6848.83700
Gentoo11947.65075

La Gentoo destaca por un body mass claramente más alto (mediana ≈ 5 kg), mientras que Adelie presenta picos de longitud de pico menores. Estos contrastes ya apuntan a hipótesis sobre diferenciación ecológica.

4.2.2 Tabla rápida de diferencias por sexo

penguins_min %>%
  group_by(sex) %>%
  summarise(across(c(bill_length_mm, body_mass_g),
                   list(mean = ~mean(.x, na.rm = TRUE),
                        sd   = ~sd(.x,   na.rm = TRUE)),
                   .names = "{.col}_{.fn}"))
sexbill_length_mm_meanbill_length_mm_sdbody_mass_g_meanbody_mass_g_sd
female42.14.53862560
male45.95.14545775
unknown44.44.84219628

Los machos en promedio presentan picos más largos y mayor masa, diferencias coherentes con la literatura biológica. La columna unknown —creada en la limpieza— permite mantener la muestra completa sin descartar registros.

4.2.3 Rango intercuartílico por isla

Para variables susceptibles de sesgo, como body_mass_g, conviene usar el rango intercuartílico (IQR) como medida de dispersión robusta:

penguins_min %>%
  group_by(island) %>%
  summarise(
    mass_iqr = IQR(body_mass_g, na.rm = TRUE)
  )

Un IQR elevado indica mayor heterogeneidad de tamaños entre individuos de la misma isla: un punto de partida para explorar nichos ecológicos o gradientes de alimento.

Próximo paso: Si alguna de estas diferencias te resulta llamativa, avanza a pruebas de hipótesis (t-test, ANOVA) o visualizaciones (ggplot2) para confirmar y comunicar tus hallazgos.

5. Visualización rápida con ggplot2

Una vez obtenidas las tablas y descriptivos, la forma más eficaz de comunicar patrones es con una buena gráfica. El paquete ggplot2 —incluido en el tidyverse— ofrece una sintaxis coherente basada en la gramática de los gráficos, lo que facilita la producción de figuras claras y reproducibles.

5.1 Gráficos fundamentales para variables categóricas y numéricas

5.1.1 Barras para una variable categórica

library(ggplot2)
# Distribución de especies
ggplot(penguins_min, aes(x = species, fill = species)) +
  geom_bar() +
  labs(title = "Distribución de especies de pingüinos",
       x = "Especie", y = "Frecuencia") +
  scale_fill_brewer(palette = "Set2") +
  theme_minimal()
  • geom_bar() cuenta registros automáticamente (stat = "count").
  • La paleta Set2 es apta para daltónicos y da contraste inmediato.

5.1.2 Histograma para una variable numérica

ggplot(penguins_min, aes(x = body_mass_g)) +
  geom_histogram(binwidth = 200, fill = "#4682B4", colour = "white") +
  labs(title = "Distribución de masa corporal",
       x = "Masa (g)", y = "Número de individuos") +
  theme_classic()

Elegir un binwidth apropiado evita “picos” artificiales. La regla de Silverman o la de Freedman–Diaconis pueden automatizar la selección, pero un valor redondo (200 g) suele ser suficiente para toy datasets.

5.1.3 Boxplot comparativo (numérico ✕ categórico)

ggplot(penguins_min, aes(x = species, y = body_mass_g, fill = species)) +
  geom_boxplot(outlier.color = "red", alpha = .7) +
  labs(title = "Masa corporal por especie",
       x = NULL, y = "Masa (g)") +
  scale_fill_brewer(palette = "Pastel1") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "none")
  • Los puntos rojos indican outliers según 1.5 × IQR.
  • Eliminar la leyenda evita redundancia cuando el llenado replica el eje X.

5.1.4 Diagrama de dispersión con codificación doble

ggplot(penguins_min,
       aes(x = bill_length_mm, y = body_mass_g,
           colour = species, shape = sex)) +
  geom_point(size = 2.5, alpha = .8) +
  labs(title = "Longitud del pico vs. masa corporal",
       x = "Longitud pico (mm)", y = "Masa (g)",
       colour = "Especie", shape = "Sexo") +
  scale_colour_brewer(palette = "Dark2") +
  theme_light()

Este gráfico revela clusters claros por especie y, con shape, las diferencias
entre sexos sin recargar con facetas.

5.2 Buenas prácticas de estética y etiquetado

RecomendaciónPor qué importaEjemplo en ggplot2
Títulos y subtítulos descriptivosContextualizan la lectura sin acudir al texto principal.labs(title = "...", subtitle = "...")
Ejes con unidades clarasEvita ambigüedad (p. ej. g vs. kg).scale_x_continuous(labels = scales::comma)
Paletas accesiblesGarantiza legibilidad para personas con daltonismo.scale_fill_brewer(palette = "Set2")
Leyendas útiles, no redundantesReducen ruido visual.theme(legend.position = "none")
Temas coherentesUnifica el estilo (fondos, tipografías).theme_minimal(base_size = 11)
Guardar en alta resoluciónEvita pixelación en informes y presentaciones.ggsave("plot.png", dpi = 300, width = 6, height = 4)

Con estas prácticas, incluso un toy dataset luce profesional y comunica una historia clara. Recuerda: una buena gráfica no lo dice todo, pero impulsa a preguntar más —y ahí comienza la investigación.

6. De la pregunta a la mini-investigación

Todo el trabajo previo (elección del toy dataset, limpieza mínima, descriptivos y gráficos) debe
converger en una pregunta clara. Esa pregunta se convierte
en una hipótesis, y con la prueba estadística adecuada
podemos aceptarla o rechazarla con evidencia.
En esta sección se muestra el camino “exprés” para pasar del
“¿será que…?” al “los datos sugieren que…”.

6.1 Formulación de hipótesis simples

Hipótesis nula (H0)
Es la posición de partida: “no hay diferencia / no hay efecto / todo es azar”.
Hipótesis alternativa (HA)
Lo que esperamos encontrar: “sí hay diferencia / sí hay efecto”.

Ejemplo de preguntaH0HA
¿La masa corporal media difiere entre pingüinos Adélie y Gentoo?μAdélie = μGentooμAdélie ≠ μGentoo
¿La preferencia por “Café” depende del género?La proporción de fanáticos del café es igual en hombres y mujeres.La proporción de fanáticos del café difiere entre géneros.

Mantén las hipótesis específicas, medibles y binarias: o se rechaza H0 o no se rechaza (nunca “se acepta” H0; simplemente no hay evidencia suficiente en su contra).

6.2 Selección de pruebas básicas (t-test, chi-cuadrado “light”)

Con toy datasets bastan dos test clásicos — fáciles de ejecutar,
interpretar y reportar:

Situación típicaPrueba recomendadaFunción en RSupuestos clave
Comparar medias de una variable numérica entre dos grupos.t-test de dos muestras (Student o Welch).t.test(x ~ grupo)Independencia, aproximada normalidad y varianzas similares (o usar Welch).
Comparar frecuencias de dos variables categóricas (contingencia 2 × k).Chi-cuadrado de independencia.chisq.test(tabla)Conteos esperados > 5 en ≥ 80 % de las celdas.

6.2.1 t-test paso a paso (penguins)

library(dplyr)
library(palmerpenguins)
penguins_clean <- penguins |> 
  filter(!is.na(body_mass_g), !is.na(species)) |> 
  filter(species %in% c("Adelie", "Gentoo"))
with(penguins_clean, t.test(body_mass_g ~ species))
  • R informa el estadístico t, grados de libertad, valor p y la diferencia de medias con intervalo de confianza 95 %.
  • Si p < 0.05 ⇒ evidencia suficiente para
    afirmar que las especies difieren en masa.

6.2.2 Chi-cuadrado exprés

tabla_bebida <- table(datos$genero, datos$bebida)
chisq.test(tabla_bebida)

R entrega χ², df y valor p.
Si p < 0.05 ⇒ la preferencia de bebida está asociada al género.

Consejos “light” para toy datasets

  • Siempre na.omit() o drop_na() antes de la prueba.
  • Comprueba normalidad con un histograma rápido o shapiro.test() (n ≤ 50).
  • Para varianzas dispares usa t.test(..., var.equal = FALSE) (Welch).
  • Si algún conteo esperado < 5: agrupa categorías o usa fisher.test().
  • Reporta: estadístico, df, valor p, estimaciones (diferencia o razón) y
    un IC 95 %. Ejemplo:
    “t(81.4)=-4.23, p<.001; Δ x̄ = –102 g
    [-150, -55], mayor masa en Gentoo”.

Con estos pasos tu mini-investigación ya tiene una pregunta acotada, una prueba apropiada y un resultado interpretable que enlaza con la historia que empezaste a contar mediante tablas y gráficos.

Vistas: 153

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *