La visualización de datos es la representación gráfica de información y datos mediante el uso de elementos como gráficos, mapas y diagramas. Su objetivo principal es hacer que volúmenes complejos de datos sean más accesibles y comprensibles, permitiendo identificar patrones, tendencias y anomalías de un vistazo.

Los paquetes que se van a trabajar con este modulo se muestran a continuación.

library(ggplot2)
library(tidyr)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

Histograma

Un histograma es una representación gráfica de la distribución de frecuencias de un conjunto de datos continuos (o discretos con muchos valores). Consiste en una serie de barras adyacentes (sin espacios entre ellas) donde el área de cada barra es proporcional a la frecuencia (absoluta o relativa) de los datos que caen dentro de un intervalo de clase o bin. Es una herramienta fundamental para explorar la forma, la centralidad, la dispersión y la presencia de valores atípicos o multimodalidad.

Los componentes del histograma son:

Eje horizontal

Eje vertical

Barras

Ejemplo en R

Para este gráfico vamos a tomar el conjunto de datos que corresponde al periodo de almacén (vida de anaquel en días) de una película fotográfica de alta velocidad. Este conjunto de datos se muestra a continuación.

# Datos 1: Vida de película (días)
vida <- c(125, 140, 121, 141, 127, 125, 127, 147, 140, 124,
          128, 150, 135, 122, 134, 132, 126, 121, 140, 143,
          120, 127, 121, 121, 121, 130, 126, 124, 142, 131,
          124, 131, 151, 141, 125, 141, 160, 137, 127, 127)

# Crear data frame
datos <- data.frame(vida)

El histograma se muestra a continuación:

# Histograma
ggplot(datos, aes(x = vida)) +
  geom_histogram(binwidth = 5, fill = "steelblue", color = "white", alpha = 0.7) +
  labs(title = "Distribución de la vida de película (días)",
       x = "Vida (días)", y = "Frecuencia") +
  theme_minimal()

A continuación se presenta un gráfico con mayor información:

# Calcular estadisticos
media_vida <- mean(vida)
sd_vida <- sd(vida)

# Cantidad de clases
k <- nclass.Sturges(vida)

ggplot(datos, aes(x = vida)) +
  
  geom_histogram(
    aes(y = after_stat(count)),
    binwidth = k,                # Numero de barras
    fill = "steelblue",
    color = "white",
    alpha = 0.7
  ) +
  
  geom_density(
    aes(y = after_stat(count * 5)),
    linewidth = 1.2
  ) +
  
  geom_vline(
    xintercept = media_vida,
    color = "red",
    linewidth = 1.2,
    linetype = "dashed"
  ) +
  
  annotate(
    "text",
    x = Inf,
    y = Inf,
    label = paste0(
      "Media = ", round(media_vida, 2),
      "\nDE = ", round(sd_vida, 2)
    ),
    hjust = 1.1,
    vjust = 2,
    size = 5,
    fontface = "bold"
  ) +
  
  labs(
    title = "Distribución de la vida de película (días)",
    x = "Vida (días)",
    y = "Frecuencia"
  ) +
  
  theme_minimal(base_size = 14) +
  
  theme(
    plot.title = element_text(
      size = 20,
      face = "bold",
      hjust = 0.5
    ),
    axis.title = element_text(
      size = 16,
      face = "bold"
    ),
    axis.text = element_text(
      size = 13
    )
  )

Diagrama de caja y bigotes

Un diagrama de caja y bigotes (o boxplot) es una representación gráfica estandarizada que resume la distribución de un conjunto de datos mediante cinco estadísticos clave: mínimo, primer cuartil (\(Q1\)), mediana (\(Q2\)), tercer cuartil (\(Q3\)) y máximo. También identifica valores atípicos (outliers) que se alejan del resto de los datos. Es ampliamente utilizado para comparar distribuciones entre grupos y detectar asimetrías o dispersiones inusuales.

Los componentes del diagrama de caja y bigotes son:

Caja

Bigotes (whiskers)

Valores atípicos (outliers)

Mínimo y máximo (no atípicos)

Ejemplo en R

Los datos de la siguiente Tabla corresponden a las temperaturas registradas en cinco silos (A, B, C, D, E) durante cinco días (Lunes a Viernes). Cada valor es la temperatura en grados Celsius en una hora crítica.

Silo Lunes Martes Miércoles Jueves Viernes
A 4.0 4.0 5.0 0.5 3.0
B 5.0 6.0 2.0 4.0 4.0
C 4.5 4.0 3.5 2.0 3.0
D 2.5 4.0 6.5 4.5 4.0
E 4.0 4.0 3.5 2.0 4.0

Obtenga un diagrama de caja y bigotes de los datos por silo y por día. A continuación se muestran los datos capturados en R.

# Crear data frame en formato ancho
datos_ancho <- data.frame(
  Silo = c("A", "B", "C", "D", "E"),
  Lunes = c(4.0, 5.0, 4.5, 2.5, 4.0),
  Martes = c(4.0, 6.0, 4.0, 4.0, 4.0),
  Miercoles = c(5.0, 2.0, 3.5, 6.5, 3.5),
  Jueves = c(0.5, 4.0, 2.0, 4.5, 2.0),
  Viernes = c(3.0, 4.0, 3.0, 4.0, 4.0)
)

# Transformar a formato largo (una fila por observación)
datos_largo <- pivot_longer(datos_ancho, 
                            cols = Lunes:Viernes, 
                            names_to = "Dia", 
                            values_to = "Temperatura")

# Mostrar primeras filas
head(datos_largo)
## # A tibble: 6 × 3
##   Silo  Dia       Temperatura
##   <chr> <chr>           <dbl>
## 1 A     Lunes             4  
## 2 A     Martes            4  
## 3 A     Miercoles         5  
## 4 A     Jueves            0.5
## 5 A     Viernes           3  
## 6 B     Lunes             5

El siguiente gráfico muestra la distribución de temperaturas observadas en cada silo durante los cinco días. Permite comparar la mediana, la dispersión y la presencia de valores atípicos.

ggplot(datos_largo, aes(x = Silo, y = Temperatura, fill = Silo)) +
  geom_boxplot(alpha = 0.7, outlier.color = "red", outlier.size = 2) +
  labs(title = "Distribución de temperaturas por silo",
       x = "Silo", y = "Temperatura (°C)") +
  theme_minimal() +
  theme(legend.position = "none")

Una manera más elegante de mostrar el gráfico y que contenga más información se muestra a continuación.

# Calcular media y desviación estándar por silo
estadisticas <- datos_largo %>%
  group_by(Silo) %>%
  summarise(
    media = mean(Temperatura, na.rm = TRUE),
    sd = sd(Temperatura, na.rm = TRUE),
    ymax = max(Temperatura, na.rm = TRUE)
  )

ggplot(datos_largo, aes(x = Silo, y = Temperatura, fill = Silo)) +
  
  # Boxplot
  geom_boxplot(
    alpha = 0.7,
    outlier.color = "red",
    outlier.size = 2
  ) +
  
  # Media como punto negro
  stat_summary(
    fun = mean,
    geom = "point",
    shape = 18,
    size = 4,
    color = "black"
  ) +
  
  # Texto con media y desviación estándar
  geom_text(
    data = estadisticas,
    aes(
      x = Silo,
      y = ymax + 0.5,
      label = paste0(
        "Media = ", round(media, 2),
        "\nDE = ", round(sd, 2)
      )
    ),
    inherit.aes = FALSE,
    size = 4,
    fontface = "bold"
  ) +
  
  labs(
    title = "Distribución de temperaturas por silo",
    x = "Silo",
    y = "Temperatura (°C)"
  ) +
  
  theme_minimal() +
  
  theme(
    legend.position = "none",
    
    # Título principal
    plot.title = element_text(
      size = 18,
      face = "bold",
      hjust = 0.5
    ),
    
    # Títulos de los ejes
    axis.title.x = element_text(
      size = 14,
      face = "bold"
    ),
    axis.title.y = element_text(
      size = 14,
      face = "bold"
    ),
    
    # Etiquetas de los ejes (ticks)
    axis.text.x = element_text(
      size = 12,
      face = "bold"
    ),
    axis.text.y = element_text(
      size = 12
    )
  )

Gráfico de barras

Un gráfico de barras (o diagrama de barras) es una representación gráfica de datos categóricos (o discretos) donde cada categoría se representa mediante una barra rectangular cuya altura (o longitud, en barras horizontales) es proporcional a la frecuencia, porcentaje, media u otra medida resumen asociada a esa categoría. Es una herramienta fundamental en estadística descriptiva para comparar magnitudes entre grupos distintos sin implicar orden numérico continuo.

Los componentes principales son:

Eje categórico

Eje numérico

Barras

Título y etiquetas

Ejemplo en R

Para este ejemplo se toman los datos utilizados en el boxplot. El registro de los datos requiere una variable del tipo factor como se muestra a continuación en la creación del data frame.

# Datos
Dia <-  rep(c("Lunes", "Martes", "Miércoles", "Jueves", "Viernes"), each = 4)
Silo <-  rep(c("Silo 1", "Silo 2", "Silo 3", "Silo 4"), times = 5)
Temperatura <- c(4.1, 3.9, 4.2, 3.8, 4.5, 4.3, 4.6, 4.2, 4.0, 4.2, 4.1, 4.1, 2.5, 2.8,
                 2.7, 2.4, 3.5, 3.7, 3.8, 3.4)

# Colocar datos en data frame
datos <- data.frame(Dia, Silo, Temperatura)

# Preparar datos para grafico de barras
df_barras <- datos %>%
  group_by(Dia) %>%
  summarise(
    Media = mean(Temperatura),
    SD = sd(Temperatura),
    n = n(),
    SE = SD / sqrt(n),
    .groups = "drop"
  )

# Media global
media_global <- mean(datos$Temperatura)

La creación del gráfico de barras se muestra a continuación

ggplot(df_barras, aes(x = Dia, y = Media, fill = Dia)) +
  geom_bar(stat = "identity", width = 0.7, show.legend = FALSE) +
  scale_fill_brewer(palette = "Set2") +
  labs(title = "Temperatura media diaria en todos los silos",
       x = "Día", y = "Temperatura media (°C)") +
  theme_minimal()

A continuación se presenta un gráfico con mayor información:

ggplot(df_barras,
       aes(x = Dia,
           y = Media,
           fill = Dia)) +

  geom_col(
    width = 0.7,
    color = "black",
    linewidth = 0.5,
    show.legend = FALSE
  ) +

  # Barras de error (±1 desviación estándar)
  geom_errorbar(
    aes(
      ymin = Media - SD,
      ymax = Media + SD
    ),
    width = 0.15,
    linewidth = 0.8
  ) +

  # Etiquetas de las medias
  geom_text(
    aes(label = round(Media, 2)),
    vjust = -1.0,
    size = 5,
    fontface = "bold"
  ) +

  # Línea de media global
  geom_hline(
    yintercept = media_global,
    color = "red",
    linewidth = 1.2,
    linetype = "dashed"
  ) +

  annotate(
    "text",
    x = 4.7,
    y = media_global + 0.45,
    label = paste(
      "Media global =",
      round(media_global, 2), "°C"
    ),
    color = "red",
    fontface = "bold",
    size = 4.5
  ) +

  scale_fill_brewer(palette = "Set2") +

  expand_limits(
    y = max(df_barras$Media + 3*df_barras$SD) + 0.5
  ) +

  labs(
    title = "Temperatura media diaria en todos los silos",
    subtitle = "Las barras de error representan ±3 desviación estándar",
    x = "Día",
    y = "Temperatura media (°C)"
  ) +

  theme_minimal(base_size = 14) +

  theme(
    legend.position = "none",

    plot.title = element_text(
      size = 20,
      face = "bold",
      hjust = 0.5
    ),

    plot.subtitle = element_text(
      size = 13,
      hjust = 0.5
    ),

    axis.title = element_text(
      size = 16,
      face = "bold"
    ),

    axis.text.x = element_text(
      size = 13,
      face = "bold"
    ),

    axis.text.y = element_text(
      size = 13
    )
  )

Diagrama de dispersión

Un diagrama de dispersión (o gráfico de dispersión) es una representación gráfica bivariada que muestra la relación entre dos variables cuantitativas. Cada observación se representa como un punto en un plano cartesiano, donde la coordenada \(x\) corresponde al valor de una variable (llamada independiente, explicativa o predictora) y la coordenada \(y\) al valor de la otra variable (dependiente, respuesta o resultado). Es una herramienta fundamental en el análisis exploratorio de datos para detectar patrones, tendencias, agrupamientos, correlaciones y valores atípicos.

Los componentes del diagrama de dispersión son:

Eje horizontal (eje X)

Eje vertical (eje Y)

Puntos (marcas)

Título y etiquetas

Línea de tendencia (opcional)

Ejemplo en R

En un laboratorio se quiere investigar la forma en que se relaciona la cantidad de fibra (madera) en la pulpa con la resistencia del papel. Se obtuvieron un conjunto de datos que se muestran a continuación.

# Crear data frame 
datos <- data.frame(
  Porcentaje_fibra = c(4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30),
  Resistencia = c(134, 145, 142, 149, 144, 160, 156, 157, 168, 166, 167, 171, 174, 183)
)

El gráfico de dispersión para este conjunto de datos se grafica con R de la siguiente forma:

# Gráfico de dispersión
ggplot(datos, aes(x = Porcentaje_fibra, y = Resistencia)) +
  geom_point(alpha = 0.7, size = 3, color = "steelblue") +   # puntos semitransparentes
  labs(title = "Relación entre porcentaje de fibra y resistencia",
       x = "Porcentaje de fibra (%)", y = "Resistencia") +
  theme_minimal() +
  theme(legend.position = "none")   # opcional, igual que en el ejemplo

A continuación se muestra un gráfico con mayor información.

# Modelo lineal
modelo <- lm(Resistencia ~ Porcentaje_fibra, data = datos)

# Coeficientes
intercepto <- coef(modelo)[1]
pendiente <- coef(modelo)[2]

# R²
R2 <- summary(modelo)$r.squared

# Correlación
correlacion <- cor(
  datos$Porcentaje_fibra,
  datos$Resistencia
)

ggplot(datos,
       aes(x = Porcentaje_fibra,
           y = Resistencia)) +

  # Puntos
  geom_point(
    size = 4,
    color = "steelblue",
    alpha = 0.8
  ) +

  # Línea de regresión
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = "red",
    linewidth = 1.2
  ) +

  # Etiquetas de cada observación
  geom_text(
    aes(label = Resistencia),
    vjust = -1,
    size = 3.5
  ) +
  
  
  scale_y_continuous(
    limits = c(120,200),
     breaks = seq(120, 200, by = 20)
  ) +

  # Ecuación y correlación
  annotate(
    "text",
    x = 6,
    y = max(datos$Resistencia),
    hjust = 0,
    size = 5,
    fontface = "bold",
    label = paste0(
      "y = ",
      round(intercepto, 2),
      " + ",
      round(pendiente, 2),
      "x",
      "\nR² = ",
      round(R2, 4),
      "\nr = ",
      round(correlacion, 4)
    )
  ) +

  labs(
    title = "Relación entre porcentaje de fibra y resistencia",
    subtitle = "Ajuste mediante regresión lineal simple",
    x = "Porcentaje de fibra (%)",
    y = "Resistencia"
  ) +

  theme_minimal() +

  theme(
    plot.title = element_text(
      size = 20,
      face = "bold",
      hjust = 0.5
    ),

    plot.subtitle = element_text(
      size = 14,
      hjust = 0.5
    ),

    axis.title = element_text(
      size = 16,
      face = "bold"
    ),

    axis.text = element_text(
      size = 13
    )
  )
## `geom_smooth()` using formula = 'y ~ x'

Gráfico de líneas

Un gráfico de líneas es una representación gráfica que muestra la evolución o tendencia de una o más variables numéricas a lo largo de una variable de orden (generalmente tiempo, pero también cualquier secuencia ordenada: distancia, orden de observación, etc.). Consiste en una serie de puntos (observaciones) conectados por segmentos de línea recta. Es especialmente útil para visualizar tendencias, cambios, ciclos y velocidades de cambio en datos secuenciales.

Los componentes esenciales del gráfico de líneas son:

Eje horizontal (eje X)

Eje vertical (eje Y)

Puntos (marcas)

Líneas

Múltiples líneas

Título, etiquetas de ejes y leyenda

Ejemplo en R

Una empresa quiere ver cómo evolucionan las horas extra a lo lago de varias semanas. Para ello recopila información de recursos humanos y se obtienen los siguientes datos.

# Crear data frame
datos <- data.frame(
  Semana = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22),
  Horas_extra = c(340, 95, 210, 809, 80, 438, 107, 180, 100, 550, 220, 50, 193, 290, 340, 115, 362, 300, 75, 93, 320, 154)
)

Con este conjunto de datos se procede a realizar el gráfico de líneas que se muestra a continuación.

# Gráfico de líneas
ggplot(datos, aes(x = Semana, y = Horas_extra)) +
  geom_line(color = "steelblue", linewidth = 1) +          # línea principal
  geom_point(color = "steelblue", size = 2, alpha = 0.7) +  # puntos para resaltar valores
  labs(title = "Evolución de horas extra por semana",
       x = "Semana", y = "Horas extra") +
  theme_minimal() +
  theme(legend.position = "none")   

A continuación se presenta un gráfico con mayor información:

media_horas <- mean(datos$Horas_extra)
sd_horas <- sd(datos$Horas_extra)

semana_max <- datos$Semana[which.max(datos$Horas_extra)]
valor_max <- max(datos$Horas_extra)

semana_min <- datos$Semana[which.min(datos$Horas_extra)]
valor_min <- min(datos$Horas_extra)

ggplot(datos,
       aes(x = Semana,
           y = Horas_extra)) +

  # Línea principal
  geom_line(
    color = "steelblue",
    linewidth = 1.2
  ) +

  # Puntos
  geom_point(
    color = "steelblue",
    size = 3.5,
    alpha = 0.8
  ) +

  # Etiquetas de valores
  geom_text(
    aes(label = Horas_extra),
    vjust = -0.8,
    size = 3.5
  ) +

  # Línea de tendencia
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = "red",
    linewidth = 1.2,
    linetype = "dashed"
  ) +

  # Línea de la media
  geom_hline(
    yintercept = media_horas,
    color = "darkgreen",
    linewidth = 1,
    linetype = "dotted"
  ) +

  # Punto máximo
  geom_point(
    data = subset(datos, Horas_extra == valor_max),
    color = "red",
    size = 5
  ) +

  # Punto mínimo
  geom_point(
    data = subset(datos, Horas_extra == valor_min),
    color = "orange",
    size = 5
  ) +

  # Resumen estadístico
  annotate(
    "text",
    x = 16,
    y = max(datos$Horas_extra),
    hjust = 0,
    vjust = 1.0,
    size = 4.0,
    fontface = "bold",
    label = paste0(
      "Media = ", round(media_horas, 1),
      "\nDE = ", round(sd_horas, 1),
      "\nMáx = ", valor_max,
      " (Sem. ", semana_max, ")",
      "\nMín = ", valor_min,
      " (Sem. ", semana_min, ")"
    )
  ) +

  scale_x_continuous(
    breaks = 1:22
  ) +
  
  scale_y_continuous(
    limits = c(0,1000),
     breaks = seq(0, 1000, by = 100)
  ) +

  labs(
    title = "Evolución de horas extra por semana",
    subtitle = "Seguimiento semanal de horas extra trabajadas",
    x = "Semana",
    y = "Horas extra"
  ) +

  theme_minimal(base_size = 14) +

  theme(
    plot.title = element_text(
      size = 20,
      face = "bold",
      hjust = 0.5
    ),

    plot.subtitle = element_text(
      size = 14,
      hjust = 0.5
    ),

    axis.title = element_text(
      size = 16,
      face = "bold"
    ),

    axis.text = element_text(
      size = 12
    ),

    panel.grid.minor = element_blank()
  )
## `geom_smooth()` using formula = 'y ~ x'