Qué muestra un histograma
Un histograma responde una pregunta sobre una variable numérica: ¿cómo se distribuyen los valores? Trocea el rango de los datos en intervalos consecutivos (bins), cuenta cuántas observaciones caen en cada uno y dibuja una barra por intervalo cuya altura es ese conteo. Donde los datos son densos, las barras son altas; donde son escasos, son bajas.
Esa única imagen te dice cosas que una media y una desviación estándar no pueden: si los datos tienen uno o dos picos, si son simétricos o están sesgados hacia una cola, y si hay valores sueltos lejos del resto. Suele ser el primerísimo gráfico que hacer al conocer un dataset nuevo, justo al lado de los números de la estadística descriptiva.
En R la función es hist(), y es una sola línea.
Tu primer histograma con hist()
Simulemos las estaturas de 200 personas, distribuidas normalmente en torno a 170 cm con una desviación estándar de 10 (consulta números aleatorios para saber qué hacen set.seed() y rnorm()):
set.seed(42)
heights <- rnorm(200, mean = 170, sd = 10)
hist(heights)
R elige los intervalos por sí mismo y dibuja una pila de barras con forma de campana: barras bajas cerca de 145 cm, que suben a lo largo de los 160, alcanzan el pico alrededor de 170 y caen simétricamente pasados los 190. El eje vertical lleva la etiqueta "Frequency" —conteos brutos— y el título y la etiqueta del eje salen del nombre de la variable.
Los valores por defecto son deliberadamente sobrios. Los argumentos habituales para vestir el gráfico funcionan todos aquí:
hist(heights,
main = "Distribution of heights",
xlab = "Height (cm)",
col = "steelblue",
border = "white")
col rellena las barras, border colorea sus contornos; border = "white" da el aspecto limpio de barras separadas que ves en la mayoría de las publicaciones. Todo lo que dice la guía de plot() sobre colores y títulos aplica sin cambios.
El ancho de intervalo: el argumento breaks
El argumento más importante de hist() es breaks, porque el ancho de los intervalos decide qué historia cuenta el gráfico. Mismos datos, dos configuraciones:
hist(heights, breaks = 5) # five wide bins: a crude, blocky bell
hist(heights, breaks = 30) # thirty narrow bins: detail, plus noise
Con breaks = 5 el histograma es tan burdo que todo parece una única joroba suave: un segundo grupo o un hueco en los datos serían invisibles. Con breaks = 30 ves la estructura fina, pero las ondulaciones aleatorias empiezan a disfrazarse de rasgos reales. Ninguno es "correcto"; lo honesto es probar varias configuraciones y ver qué rasgos sobreviven.
breaks acepta tres formas:
- Un número —
breaks = 30— una sugerencia del número de intervalos. R lo ajusta para caer en límites ordenados, así que puedes acabar con 28 o 33 intervalos. Esto sorprende a todo el mundo una vez. - Un vector de puntos de corte —
breaks = seq(140, 200, by = 5)— bordes exactos de los intervalos, sin negociación. Úsalo cuando los intervalos deban alinearse entre varios histogramas que estés comparando. - El nombre de una regla —
breaks = "FD"para Freedman–Diaconis, que elige el ancho a partir de la dispersión de los datos y el tamaño de la muestra, y se comporta bien con datos sesgados.
Histogramas de densidad y la curva normal
Por defecto las alturas de las barras son conteos (freq = TRUE). Establecer freq = FALSE reescala las barras para que su área total sea 1: la escala de densidad. La forma no cambia; el eje vertical sí. El sentido de hacerlo es que un histograma de densidad vive en la misma escala que una función de densidad de probabilidad, así que puedes superponer una curva teórica directamente sobre los datos:
hist(heights,
freq = FALSE,
col = "gray90",
main = "Heights vs. a normal curve",
xlab = "Height (cm)")
curve(dnorm(x, mean = mean(heights), sd = sd(heights)),
add = TRUE, col = "tomato", lwd = 2)
curve() con add = TRUE dibuja la campana sobre el histograma existente (la x dentro de dnorm(x, ...) es un marcador de posición que curve() rellena, no una variable tuya). Si las barras se ciñen a la curva, un modelo normal es razonable; donde se abomban lejos de ella —una cola pesada, un segundo pico— al modelo le falta algo. Si omites freq = FALSE, la curva se arrastrará inútilmente por el fondo del gráfico, porque los conteos y las densidades están en escalas distintas.
Los números detrás de las barras
hist() no solo dibuja: devuelve la división en intervalos como una lista. Con plot = FALSE se salta el dibujo por completo y solo calcula, lo que significa que este sí puedes ejecutarlo aquí mismo:
h$counts es el histograma como datos: cada número es la altura de una barra. La línea table(cut(...)) es el equivalente en modo texto —cut() agrupa los valores en intervalos, table() cuenta cada intervalo— y es una comprobación de cordura decente para imprimir antes de un gráfico, o en su lugar. Si asignas sin plot = FALSE (h <- hist(heights)), R dibuja y además devuelve la lista; la asignación no suprime el gráfico.
Histogramas con ggplot2
La versión de ggplot2 cambia breaks por binwidth, que a menudo es el control más natural: dices cuán ancho es un intervalo en unidades de los datos en lugar de cuántos intervalos quieres:
library(ggplot2)
ggplot(data.frame(heights), aes(x = heights)) +
geom_histogram(binwidth = 5, fill = "steelblue", color = "white") +
labs(title = "Distribution of heights", x = "Height (cm)", y = "Count")
binwidth = 5 significa que cada barra cubre 5 cm. ggplot2 te avisa si dejas binwidth sin definir y usa 30 intervalos por defecto sin más: haz caso al aviso, porque el valor por defecto rara vez es el ancho correcto para tus datos. Para un vistazo rápido a una variable, hist() es menos tecleo; ggplot2 se gana el puesto cuando el histograma necesita facetas, grupos o un tema coherente con el resto de tus figuras.
Lo que te llevas
- Un histograma muestra la distribución de una variable numérica:
hist(x)y listo. breakses el argumento que importa: un número es solo una sugerencia, un vector fija los bordes exactos,"FD"elige un ancho defendible. Prueba siempre más de una configuración.freq = FALSEcambia a la escala de densidad, que es lo que permite quecurve(dnorm(...), add = TRUE)superponga una curva normal con sentido.hist(x, plot = FALSE)devuelve los intervalos como datos ($breaks,$counts,$mids);table(cut(x, breaks))es el equivalente solo de texto.- En ggplot2,
geom_histogram(binwidth = ...), y definebinwidthtú mismo.
Lo siguiente: el boxplot, el gráfico de distribución que brilla de verdad cuando comparas grupos lado a lado.
Preguntas frecuentes
¿Cómo se hace un histograma en R?
Llama a hist(x) sobre un vector numérico. R divide el rango de x en intervalos (bins) y dibuja una barra por intervalo, cuya altura muestra cuántos valores caen dentro. Añade breaks = para controlar el número de intervalos y col = para colorear las barras.
¿Qué hace el argumento breaks en hist()?
Controla la división en intervalos. Un número único como breaks = 30 es una sugerencia de cuántos intervalos usar (R lo redondea a límites ordenados), un vector como breaks = seq(140, 200, by = 5) fija los puntos de corte exactos, y breaks = "FD" usa la regla de Freedman–Diaconis.
¿Cómo se superpone una curva normal sobre un histograma en R?
Dibuja el histograma en la escala de densidad con freq = FALSE y luego añade la curva con curve(dnorm(x, mean = mean(data), sd = sd(data)), add = TRUE). En la escala de frecuencias la curva quedaría inútilmente pegada a cero, así que freq = FALSE es imprescindible.
¿Cuál es la diferencia entre un histograma y un gráfico de barras?
Un histograma agrupa en intervalos una variable numérica, así que el eje horizontal es una escala continua y las barras se tocan. Un gráfico de barras compara categorías distintas, así que las barras van separadas. En R eso es hist() para números y barplot() para conteos de categorías.