Al comparar distribuciones de varios variables numéricas, los gráficos son herramientas clave para visualizar patrones. Aunque histogramas y gráficos de densidad permiten representar varias distribuciones en un mismo eje, el exceso de grupos puede comprometer la claridad del mensaje.
Consideremos un conjunto de datos que muestra cómo las personas interpretan probabilidades asociadas a frases como "Highly likely". El objetivo es analizar la distribución de las respuestas dadas por sujetos para diferentes expresiones.
# Carga de dependencias
library(tidyverse)
library(hrbrthemes)
library(viridis)
library(patchwork)
# Descarga de datos
raw_data <- read.table("https://raw.githubusercontent.com/zonination/perceptions/master/probly.csv",
header = TRUE, sep = ",")
# Preprocesamiento
processed_data <- raw_data %>%
gather(key = "phrase", value = "score") %>%
mutate(phrase = gsub("\\.", " ", phrase)) %>%
mutate(score = round(as.numeric(score), 0))
# Muestra inicial
head(processed_data)
nrow(processed_data)
Este conjunto contiene 782 observaciones con etiquetas como "Almost No Chance", "About Even", entre otras. Para fines ilustrativos, se seleccionan solo cuatro categorías clave:
subset_data <- processed_data %>%
filter(phrase %in% c("Almost No Chance", "About Even", "Probable", "Almost Certainly")) %>%
mutate(phrase = fct_reorder(phrase, score))
head(subset_data)
nrow(subset_data)
Con solo cuatro grupos, una gráfica de densidad superpuesta resulta clara y efectiva:
# Etiquetas de referencia para anotaciones
annotations <- data.frame(
phrase = c("Almost No Chance", "About Even", "Probable", "Almost Certainly"),
x_pos = c(5, 53, 65, 79),
y_pos = c(0.15, 0.4, 0.06, 0.1)
)
ggplot(subset_data, aes(x = score, color = phrase, fill = phrase)) +
geom_density(alpha = 0.6) +
scale_fill_viridis(discrete = TRUE) +
scale_color_viridis(discrete = TRUE) +
geom_text(data = annotations, aes(x = x_pos, y = y_pos, label = phrase, color = phrase),
hjust = 0, size = 4.5) +
theme(
legend.position = "none",
panel.spacing = unit(0.1, "lines"),
strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Probabilidad asignada (%)")
Sin embargo, al incluir todos los grupos (más de 20), el gráfico pierde legibilidad. La superposición de múltiples curvas dificulta la identificación de patrones.
Alternativas recomendadas
1. Gráfico de cajas (boxplot)
Ideal para resumir distribuciones con poca sobrecarga visual. Es útil cuando hay muchos grupos, especialmente si se rotan los ejes.
ggplot(processed_data, aes(x = phrase, y = score, fill = phrase)) +
geom_boxplot() +
geom_jitter(color = "grey", alpha = 0.3, size = 0.9) +
scale_fill_viridis(discrete = TRUE) +
theme(legend.position = "none") +
coord_flip() +
xlab("") +
ylab("Probabilidad asignada (%)")
Este tipo de gráfico destaca valores centrales y dispersión, aunque oculta detalles sobre la forma exacta de la distribución.
2. Gráfico de violín (violin plot)
Mejor que el boxplot cuando se desea mostrar la forma completa de la distribución. Sin embargo, con muchos grupos, los trazos pueden volverse demasiado estrechos y difíciles de distinguir.
ggplot(processed_data, aes(x = phrase, y = score, fill = phrase, color = phrase)) +
geom_violin(width = 2.1, size = 0.2) +
scale_fill_viridis(discrete = TRUE) +
scale_color_viridis(discrete = TRUE) +
theme(legend.position = "none") +
coord_flip() +
xlab("") +
ylab("Probabilidad asignada (%)")
Aparece una advertencia común: position_dodge requires non-overlapping x intervals, lo cual indica que el método de desplazamiento no funciona bien con etiquetas repetidas.
3. Gráfico de densidad con facetas
Una solución eficaz para múltiples grupos es dividirlos en subgráficos independientes. Esto permite ver cada distribución sin superposición.
ggplot(processed_data, aes(x = score, color = phrase, fill = phrase)) +
geom_density(alpha = 0.6) +
scale_fill_viridis(discrete = TRUE) +
scale_color_viridis(discrete = TRUE) +
theme(
legend.position = "none",
panel.spacing = unit(0.1, "lines"),
strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Probabilidad asignada (%)") +
facet_wrap(~phrase, scales = "free_y")
Cada panel muestra la distribución de un grupo indviidualmente, facilitando análisis detallado, aunque complica la comparación directa entre ellos.
4. Histogramas con facetas
Similar a los gráficos de densidad, pero usando barras. Es útil cuando se quiere enfatizar frecuencias absolutas.
ggplot(processed_data, aes(x = score, color = phrase, fill = phrase)) +
geom_histogram(alpha = 0.6, binwidth = 5) +
scale_fill_viridis(discrete = TRUE) +
scale_color_viridis(discrete = TRUE) +
theme(
legend.position = "none",
panel.spacing = unit(0.1, "lines"),
strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Probabilidad asignada (%)") +
facet_wrap(~phrase)
En este caso, el eje Y representa conteo absoluto, lo que permite comparar tamaños de muestra entre grupos.
5. Gráfico de colinas (ridge plot)
La mejor opción cuando se requiere equilibrio entre claridad visual y comparación múltiple. Combina ventajas de los violin plots con una disposición compacta vertical.
library(ggridges)
ggplot(processed_data, aes(y = phrase, x = score, fill = phrase)) +
geom_density_ridges(alpha = 0.6, bandwidth = 4) +
scale_fill_viridis(discrete = TRUE) +
scale_color_viridis(discrete = TRUE) +
theme(
legend.position = "none",
panel.spacing = unit(0.1, "lines"),
strip.text.x = element_text(size = 8)
) +
xlab("") +
ylab("Probabilidad asignada (%)")
Este gráfico permite ver fácilmente diferencias entre grupos, con distribuciones superpuestas de forma natural, ideal para grandes conjuntos de datos.
Conclusión
Cuando hay más de 4–5 grupos, evitar gráficos de densidad superpuestos. En su lugar, usar facet_wrap, boxplots rotados, o preferiblemente ridge plots para mantener la claridad visual mientras se preserva la capacidad de comparación.