Capítulo15 Análisis Exploratorio
Fecha de la última revisión
## [1] "2026-09-20"
El tema proviene de los siguientes sitios.
English: https://r4ds.had.co.nz/exploratory-data-analysis.html
Español: https://es.r4ds.hadley.nz/07-eda.html
15.1 Temas
- Variación
- Valores típicos y valores inusuales
- Valores faltantes
- Covariación
- Patrones y modelos
- Argumentos en ggplot2
15.3 Términos importantes
Antes de empezar conviene tener claros cuatro términos, porque todo el capítulo los usa:
- una variable es una cantidad, cualidad o propiedad que se puede medir (el quilate de un diamante, su color);
- un valor es el estado de esa variable cuando se mide (0.23 quilates, el color E);
- una observación es el conjunto de valores medidos en la misma unidad y en las mismas condiciones (un diamante, con todas sus medidas);
- en datos tabulados cada valor ocupa su propia celda, cada variable su propia columna y cada observación su propia fila.
15.4 ¿Qué es el análisis exploratorio?
El análisis exploratorio de datos, o EDA por sus siglas en inglés, no es una receta con pasos fijos: es un ciclo de preguntas. Uno se hace una pregunta sobre los datos, la contesta con un resumen o con una gráfica rápida, y lo que encuentra sugiere la próxima pregunta. Al principio las preguntas son malas, porque todavía no se conocen los datos; después de veinte preguntas malas aparecen las dos o tres buenas, que son las que valen.
Casi todas las preguntas del EDA se reducen a dos:
- ¿Qué tipo de variación hay dentro de cada una de mis variables?
- ¿Qué tipo de covariación hay entre mis variables?
Las gráficas de esta etapa son rápidas y feas a propósito. No son para publicar, son para mirar. La gráfica bonita, con títulos y colores escogidos, viene después, cuando ya se sabe qué se quiere enseñar.
El análisis exploratorio de datos (EDA) fue impulsado por John W. Tukey, quien publicó el libro Exploratory Data Analysis en 1977. Su idea: antes de probar hipótesis, hay que mirar los datos con gráficos sencillos para descubrir patrones, valores típicos y atípicos.
count() y los geom_* de exploración: resumir y visualizar.
count(variable): cuenta cuántas observaciones hay por categoría.- Una variable:
geom_histogram()/geom_bar()para ver su distribución. - Dos variables:
geom_point(),geom_boxplot(),geom_count(),geom_tile(),geom_hex()según los tipos.
15.5 Variación
La variación es la tendencia de una variable a cambiar de medición en medición. Todo varía: si mides el mismo diamante dos veces con la misma balanza obtendrás números ligeramente distintos, y si mides diamantes distintos las diferencias serán mucho mayores. La forma de esa variación, es decir, cómo se reparten los valores, es lo primero que hay que mirar.
15.5.1 Una variable categórica
Con una variable categórica la pregunta es sencilla: ¿cuántas observaciones hay en cada categoría? Se contesta de dos maneras, con una tabla y con una gráfica, y conviene hacer las dos porque dicen cosas distintas.
## # A tibble: 5 × 2
## corte n
## <ord> <int>
## 1 Regular 1610
## 2 Bueno 4906
## 3 Muy bueno 12082
## 4 Premium 13791
## 5 Ideal 21551

Ya aparece algo que no era obvio: el corte Ideal, que es el mejor, es también
el más común. Esa es exactamente la clase de observación que abre una
pregunta nueva.
15.5.2 Una variable continua
Con una variable continua hay que agrupar los valores en intervalos antes de
contarlos, y el ancho del intervalo (binwidth) cambia por completo lo que se
ve. No hay un ancho correcto: hay que probar varios.

Con intervalos de medio quilate se ve una distribución sesgada hacia la derecha y poco más. Vale la pena mirar de cerca los diamantes pequeños, que son la inmensa mayoría, con un intervalo mucho más fino:
pequenos <- diamantes |> filter(quilate < 3)
ggplot(pequenos, aes(x = quilate)) +
geom_histogram(binwidth = 0.01)
El objeto pequenos que se acaba de crear se vuelve a usar más adelante, en la
sección de dos variables continuas. Si corres los bloques salteados y R te dice
que no encuentra pequenos, vuelve a correr este.
Ahora la gráfica cuenta otra historia: hay picos en los valores redondos
(0.3, 0.5, 0.7, 1.0 quilates) y muy pocos diamantes justo por debajo de cada uno.
Eso no es biología ni geología, es mercado: conviene cortar la piedra para que
llegue al número redondo. Con binwidth = 0.5 ese patrón era invisible.
Nunca te quedes con el primer histograma. Cambia el binwidth al menos tres
veces. Un intervalo muy ancho esconde los patrones; uno muy fino los ahoga en
ruido.
count() y cut_width(): contar por categoría y por intervalo.
count(x): tabla de frecuencias de una variable categórica;count(x, y)la hace para las combinaciones de dos.cut_width(x, ancho): (ggplot2) corta una variable continua en intervalos del mismo ancho y devuelve una variable categórica.- Juntas:
count(cut_width(quilate, 0.5))es la versión en tabla de lo que el histograma enseña en gráfica.
## # A tibble: 11 × 2
## `cut_width(quilate, 0.5)` n
## <fct> <int>
## 1 [-0.25,0.25] 785
## 2 (0.25,0.75] 29498
## 3 (0.75,1.25] 15977
## 4 (1.25,1.75] 5313
## 5 (1.75,2.25] 2002
## 6 (2.25,2.75] 322
## 7 (2.75,3.25] 32
## 8 (3.25,3.75] 5
## 9 (3.75,4.25] 4
## 10 (4.25,4.75] 1
## 11 (4.75,5.25] 1
15.5.3 Valores típicos
Frente a un histograma, las preguntas útiles son siempre las mismas:
- ¿cuáles valores son los más comunes, y por qué?
- ¿cuáles son raros, y eso encaja con lo que esperabas?
- ¿hay patrones raros, como picos regulares o huecos?
- si hay grupos separados, ¿en qué se distinguen las observaciones de cada grupo?
Un hueco en un histograma casi siempre significa una de dos cosas: o hay subpoblaciones distintas mezcladas en la misma tabla, o el instrumento de medición no puede producir esos valores.
15.5.4 Valores inusuales
Los valores extremos a veces son errores de tecleo y a veces son el hallazgo del estudio. En un histograma con muchas observaciones son difíciles de ver, porque las barras que los contienen tienen altura casi cero:

La solución no es cambiar los datos sino acercar la vista al eje vertical:

Ahora sí se ven las barras diminutas de los extremos. El paso siguiente es siempre mirar esas observaciones una por una:
inusuales <- diamantes |>
filter(tabla < 50 | tabla > 70) |>
select(precio, quilate, corte, tabla) |>
arrange(tabla)
inusuales## # A tibble: 12 × 4
## precio quilate corte tabla
## <int> <dbl> <ord> <dbl>
## 1 4997 1.04 Ideal 43
## 2 474 0.29 Muy bueno 44
## 3 3951 1 Regular 49
## 4 630 0.3 Regular 49
## 5 1633 0.68 Regular 71
## 6 2100 0.7 Regular 73
## 7 2368 0.71 Regular 73
## 8 2579 0.5 Regular 73
## 9 2579 0.5 Regular 73
## 10 2362 0.79 Regular 76
## 11 2301 0.81 Regular 79
## 12 13387 2.01 Regular 95
coord_cartesian(): acercar la vista sin tocar los datos.
ylim = c(0, 50): recorta lo que se muestra en el eje vertical.- Diferencia con
ylim()oscale_y_continuous(limits = ...): esas dos eliminan las observaciones que quedan fuera antes de calcular la gráfica, y por eso pueden cambiar el resultado;coord_cartesian()solo mueve la ventana.
No borres un valor inusual porque estorba. Primero averigua por qué es
inusual. Si es un error de captura documentado, se sustituye por NA; si no
sabes qué es, se reportan los dos análisis, con y sin él, y se dice en el texto
lo que cambia.
15.6 Valores faltantes
Cuando decides que un valor no es de fiar, tienes dos caminos. El primero es
descartar la fila entera con filter(), y casi nunca es buena idea: por un
valor sospechoso pierdes todas las demás medidas de esa observación. El segundo,
mejor, es sustituir solo ese valor por NA y quedarte con el resto de la
fila.
between() e if_else(): marcar valores fuera de rango.
between(x, min, max): devuelveTRUEsi el valor está dentro del intervalo, límites incluidos. Es más corto y más legible quex >= min & x <= max.if_else(condicion, valor_si, valor_no): escoge entre dos valores. A diferencia deifelse()de base R, respeta el tipo de dato, y por eso hay que escribirNA_real_(noNA) cuando la columna es numérica.
diamantes2 <- diamantes |>
mutate(tabla = if_else(between(tabla, 50, 70), tabla, NA_real_))
sum(is.na(diamantes2$tabla))## [1] 12
En R los valores faltantes se representan con NA. Funciones como mean() o sum() los propagan y devuelven NA, por eso conviene usar el argumento na.rm = TRUE.
## [1] NA
## [1] 57.45517
Hay una pregunta que casi nadie se hace y que suele ser la más interesante:
¿en qué se diferencian las observaciones que tienen el dato de las que no lo
tienen? En vuelos, otro conjunto del paquete datos, un NA en el atraso de salida
no es ruido:
significa que el vuelo se canceló.
## # A tibble: 2 × 2
## cancelado n
## <lgl> <int>
## 1 FALSE 328521
## 2 TRUE 8255
La idea de que el patrón de los datos que faltan es en sí mismo un dato se
formalizó con Donald B. Rubin en 1976, en el artículo Inference and missing
data. De ahí vienen los términos que todavía se usan: faltantes completamente al
azar, faltantes al azar y faltantes no al azar. La diferencia importa: solo en el
primer caso quitar los NA deja el análisis intacto.
15.7 Covariación: una variable categórica y una continua
La covariación es la tendencia de dos o más variables a cambiar juntas. Con una variable categórica y una continua, la primera idea es superponer las distribuciones:

Esta gráfica no sirve de mucho, y vale la pena entender por qué: las categorías tienen tamaños muy distintos, así que las curvas altas son simplemente las categorías con más diamantes. Para comparar formas hay que poner las curvas en la misma escala, con la densidad en lugar del conteo:
ggplot(diamantes, aes(x = precio, y = after_stat(density))) +
geom_freqpoly(aes(color = corte), binwidth = 500)
after_stat(density) le pide a geom_freqpoly() que en lugar del conteo dibuje
la densidad, es decir, el conteo dividido por el total de cada grupo, de modo
que el área bajo cada curva sea 1 y las cinco curvas sean comparables.
Aun así, cinco curvas encimadas se leen mal. El diagrama de caja dice lo mismo de forma mucho más compacta:

Y aquí sale el resultado que sorprende a todo el mundo: los diamantes de mejor corte son, en promedio, los más baratos. No es un error de los datos. Es una pregunta nueva, y la respuesta está en el quilate, que es la variable que de verdad manda en el precio.
Cuando la variable categórica no tiene un orden natural, conviene ordenarla por la mediana antes de graficar, porque así la gráfica se lee de un vistazo:
ggplot(diamantes, aes(x = reorder(color, precio, FUN = median), y = precio)) +
geom_boxplot() +
labs(x = "color, ordenado por la mediana del precio")
geom_boxplot() y reorder(): comparar distribuciones entre grupos.
- La caja va del primer al tercer cuartil, y la línea de adentro es la mediana.
- Los bigotes llegan hasta la observación más lejana que esté a menos de 1.5 rangos intercuartiles de la caja; los puntos sueltos que quedan fuera son los valores extremos.
reorder(categoria, valor, FUN = median): reordena los niveles de la variable categórica según un resumen del valor, casi siempre la mediana.
15.8 Dos variables categóricas
Con dos categóricas hay que contar las combinaciones. geom_count() dibuja un
punto cuyo tamaño es el conteo:

La alternativa es contar primero y colorear después. Esta versión suele leerse mejor cuando hay muchas combinaciones:

El ojo humano compara tamaños mejor que colores. Si la gráfica es para
decidir algo, geom_count() o una tabla de count() suelen ser más honestas que
un mapa de calor bonito.
15.9 Dos variables continuas
El diagrama de dispersión es la herramienta obvia, y con muchas observaciones es también la que más engaña, porque los puntos se apilan unos encima de otros:

Hay tres maneras de arreglarlo. La primera es hacer los puntos transparentes, para que la densidad se vea como una mancha más oscura:

La segunda es dividir el plano en celdas y contar cuántos puntos caen en cada una, igual que un histograma pero en dos dimensiones:

geom_hex() hace lo mismo con celdas hexagonales y muchos lo prefieren, pero
necesita el paquete hexbin instalado. geom_bin2d() viene con ggplot2 y no
requiere nada más.
La tercera es convertir una de las dos continuas en categórica con
cut_width(), y usar diagramas de caja:

Esta última tiene una ventaja sobre las otras dos: además de la tendencia, enseña cómo cambia la dispersión del precio a medida que crece el quilate.
15.10 Patrones y modelos
Un patrón es una pista de que dos variables están relacionadas. Cuando encuentres uno, hazte estas preguntas antes de creértelo:
- ¿podría ser coincidencia, dado el número de observaciones?
- ¿qué tan fuerte es la relación?
- ¿qué otras variables podrían estar detrás?
- ¿cambia el patrón si miras subgrupos por separado?
La covariación es útil porque reduce la incertidumbre: si sabes el quilate,
sabes bastante sobre el precio. Un modelo es la herramienta que separa el
patrón del resto. Si ajustas el precio en función del quilate y luego miras lo
que sobra (los residuales), estás mirando el precio ya limpio del efecto del
tamaño, y ahí es donde por fin se ve que el corte Ideal sí vale más.
Ese es el tema del capítulo de modelos con modelr, más adelante en el libro.
Por ahora basta con quedarse con la idea: el EDA hace las preguntas, el modelo
contesta la que quedó en pie.
15.11 Ejercicios del libro R4DS
Hacer los ejercicios de las siguientes secciones del libro en español:
- sección 7.3.4 (variación),
- sección 7.4.1 (valores faltantes),
- sección 7.5.1.1 (covariación: categórica y continua),
- sección 7.5.2.1 (dos variables categóricas),
- sección 7.5.3.1 (dos variables continuas).
15.12 Actividades del capítulo
Cómo se trabaja este capítulo. Este capítulo se entrega en dos actividades independientes, cada una pensada para hora y media entre leer y entregar.
- Actividad 1, variación: una variable a la vez. Se apoya en las secciones Variación, Valores típicos, Valores inusuales y Valores faltantes.
- Actividad 2, covariación: dos variables a la vez. Se apoya en las secciones Covariación, Dos variables categóricas, Dos variables continuas y Patrones y modelos.
Las dos se pueden trabajar en pareja, dos personas, pero cada estudiante entrega su propio archivo y escribe en el encabezado con quién trabajó. Las explicaciones en palabras las redacta cada quien por su cuenta.
Cada ejercicio se entrega con tres cosas: el script, el resultado (que la
gráfica o la tabla se vean) y una explicación en palabras. En un capítulo de
exploración la explicación es lo más importante: una gráfica sin lectura no
contesta nada. Los ejercicios usan millas y paises del paquete datos, no
diamantes, que es con lo que se enseña aquí.
Las hojas completas para entregar están en
Ejercicios/Ejercicios_Capitulo_15_Actividad_1_variacion.Rmd y
Ejercicios/Ejercicios_Capitulo_15_Actividad_2_covariacion.Rmd.
15.12.1 Actividad 1: variación
15.12.1.1 Ejercicio 1.1. Variación de una variable categórica
Datos: millas. Cuenta los vehículos por clase con count(), ordena la tabla
de mayor a menor y haz la gráfica equivalente con geom_bar().
Verificación: la tabla debe tener 7 filas, la suma de los conteos debe dar
234, y suv debe ser la clase más común.
En palabras: ¿por qué la tabla y la gráfica no son redundantes? Di algo que se vea mejor en una y algo que se vea mejor en la otra, y por qué el desbalance entre clases importa para todo lo que calcules después por clase.
15.12.1.2 Ejercicio 1.2. El binwidth cambia la historia
Datos: paises, solo el año 2007. Haz tres histogramas de esperanza_de_vida
con binwidth de 10, de 2 y de 0.5.
Verificación: los tres histogramas tienen que sumar 142 países.
En palabras: ¿cuál de los tres enseña que la distribución tiene dos grupos? ¿Qué esconde el de intervalos anchos y qué inventa el de intervalos muy finos? Escoge uno para una figura de informe y justifica el número.
15.12.1.3 Ejercicio 1.3. Valores inusuales sin borrarlos
Datos: paises de 2007, variable pib_per_capita. Haz un histograma, acércate
al eje vertical con coord_cartesian() hasta ver las barras de la cola derecha,
saca en una tabla los países que están en esa cola y calcula la media y la
mediana con ellos y sin ellos.
Verificación: tu tabla de países extremos debe tener menos de diez filas y todas deben ser del año 2007.
En palabras: ¿son errores o son datos verdaderos? Justifica mirando cuáles países son, no la forma del histograma. ¿Por qué se movió la media y por qué la mediana casi no?
15.12.1.4 Ejercicio 1.4. Sustituir por NA, no borrar la fila
Datos: millas. Con if_else() y between(), crea millas2 donde el valor de
autopista se sustituya por NA_real_ cuando esté fuera del intervalo de 12 a
40 millas por galón.
Verificación: millas2 debe seguir teniendo 234 filas, y sum(is.na(...))
debe decirte cuántos valores marcaste.
En palabras: compara el promedio de autopista con na.rm = TRUE y sin él.
¿Por qué es mejor esto que haber usado filter() para botar las filas?
15.12.1.5 Ejercicio 1.5 (BONO). ¿La bimodalidad es real?
Vuelve al histograma de esperanza_de_vida en paises de 2007 y sepáralo por
continente con facet_wrap(~ continente).
Verificación: la suma de los paneles sigue siendo 142 países.
En palabras: ¿los dos grupos son un accidente del ancho del intervalo o corresponden a continentes distintos? Un hueco en un histograma muchas veces quiere decir que hay subpoblaciones distintas mezcladas en la misma tabla: explica si es el caso aquí.
15.12.2 Actividad 2: covariación
15.12.2.1 Ejercicio 2.1. Una categórica y una continua
Datos: millas. Haz un diagrama de caja de autopista según clase, y después
el mismo diagrama con las clases ordenadas por la mediana usando reorder().
Verificación: pickup debe quedar en el extremo de las medianas más bajas.
En palabras: además de la mediana, ¿qué clase tiene la caja más ancha, y qué significa eso? Una mediana alta con mucha dispersión, ¿es mejor o peor noticia que una mediana un poco más baja pero consistente?
15.12.2.2 Ejercicio 2.2. Dos variables categóricas
Datos: millas, variables clase y cilindros (trátala como categórica con
factor()). Cuenta las combinaciones con count() y dibújalas de las dos
maneras del capítulo: con geom_count() y con geom_tile().
Verificación: cilindros tiene 4 valores distintos, y no todas las
combinaciones de clase y cilindros existen.
En palabras: nombra dos combinaciones que no aparecen en los datos y explica por qué tiene sentido que no existan. ¿Cuál de las dos gráficas enseña mejor esos huecos?
15.12.2.3 Ejercicio 2.3. Dos variables continuas
Datos: millas, cilindrada contra autopista. Haz las tres versiones del
capítulo: puntos con alpha, geom_bin2d(), y diagramas de caja agrupando con
cut_width(cilindrada, 1).
Verificación: las tres tienen que enseñar la misma tendencia general.
En palabras: describe la tendencia y di si es recta. ¿Cuál de las tres enseña
mejor la dispersión de autopista para un mismo tamaño de motor? ¿Y cuál
usarías para una presentación de cinco minutos? Son dos respuestas distintas.
15.12.2.4 Ejercicio 2.4. El patrón escondido en los subgrupos
Sigue con cilindrada y autopista en millas, pero ahora colorea los puntos
por clase y sepáralos con facet_wrap(~ clase).
Verificación: debe verse que la relación no es igual en todas las clases.
En palabras: ¿qué clase se sale de la tendencia general y por qué? Esta es la
misma situación del corte Ideal en diamantes: una tercera variable estaba
escondiendo el patrón. Explica cuál es aquí esa tercera variable, y fíjate en que
no es una columna de la tabla.
15.12.2.5 Ejercicio 2.5 (BONO). Las tres técnicas en otro conjunto
Datos: paises de 2007. Mira pib_per_capita contra esperanza_de_vida con un
diagrama de dispersión, y después colorea o separa por continente.
Verificación: son 142 países.
En palabras: ¿la relación es recta? ¿Dónde se aplana y qué significa eso? Con lo que dice la sección Patrones y modelos, ¿podría haber una tercera variable detrás? Nombra una candidata y di cómo la comprobarías.