# Cargar librerías necesarias
library(tidyverse)
library(gt)
library(paletteer) # Para paletas de colores adicionales
# Configuración global
options(scipen = 999) # Evitar notación científicaTutorial: Optimización de Tablas Anchas con gt
Técnicas avanzadas para mejorar la presentación de datos tabulares
Introducción
El paquete gt es una herramienta potente para crear tablas de alta calidad en R. Este tutorial se centra en técnicas específicas para optimizar la presentación de tablas anchas, un desafío común en el análisis de datos hidrológicos y ambientales.
Datos de ejemplo: Serie temporal hidrológica
Vamos a crear un conjunto de datos que simula mediciones hidrológicas mensuales en diferentes estaciones de aforo.
# Simular datos de caudales mensuales en m³/s
set.seed(2024)
# Crear datos de ejemplo - Serie temporal hidrológica
datos_hidrologicos <- tibble(
estacion = rep(c("EA001_Río_Tajo", "EA002_Río_Duero", "EA003_Río_Ebro",
"EA004_Río_Guadalquivir", "EA005_Río_Guadiana"), each = 12),
mes = rep(month.name, 5),
caudal_medio = runif(60, 10, 500) |> round(2),
caudal_max = caudal_medio * runif(60, 1.2, 2.5) |> round(2),
caudal_min = caudal_medio * runif(60, 0.3, 0.8) |> round(2),
precipitacion = runif(60, 0, 150) |> round(1),
temperatura = runif(60, 5, 35) |> round(1),
evaporacion = runif(60, 20, 180) |> round(1),
nivel_embalse = runif(60, 30, 95) |> round(1),
calidad_agua = sample(c("Excelente", "Buena", "Aceptable", "Deficiente"), 60,
replace = TRUE, prob = c(0.3, 0.4, 0.2, 0.1))
) |>
mutate(
mes = factor(mes, levels = month.name),
cuenca = str_extract(estacion, "Río_.*") |> str_remove("Río_")
)
# Transformar a formato ancho para demostrar el problema
datos_anchos <- datos_hidrologicos |>
select(cuenca, mes, caudal_medio, precipitacion, temperatura) |>
pivot_wider(
names_from = mes,
values_from = c(caudal_medio, precipitacion, temperatura),
names_glue = "{mes}_{.value}"
)
glimpse(datos_anchos)Rows: 5
Columns: 37
$ cuenca <chr> "Tajo", "Duero", "Ebro", "Guadalquivir", "Guad…
$ January_caudal_medio <dbl> 420.10, 354.74, 400.70, 36.52, 330.63
$ February_caudal_medio <dbl> 167.23, 262.73, 153.23, 483.40, 328.74
$ March_caudal_medio <dbl> 343.38, 230.23, 311.47, 20.85, 40.05
$ April_caudal_medio <dbl> 352.10, 422.69, 409.64, 327.21, 373.13
$ May_caudal_medio <dbl> 233.93, 64.05, 10.26, 437.70, 231.95
$ June_caudal_medio <dbl> 353.70, 432.98, 20.35, 456.12, 249.85
$ July_caudal_medio <dbl> 213.70, 74.22, 226.15, 315.70, 379.08
$ August_caudal_medio <dbl> 158.57, 154.76, 152.24, 202.05, 360.77
$ September_caudal_medio <dbl> 439.53, 33.16, 96.34, 427.21, 19.75
$ October_caudal_medio <dbl> 68.33, 64.88, 486.96, 229.61, 104.04
$ November_caudal_medio <dbl> 451.92, 343.41, 340.83, 213.68, 233.65
$ December_caudal_medio <dbl> 477.02, 426.50, 343.67, 146.82, 146.32
$ January_precipitacion <dbl> 16.5, 18.3, 127.7, 43.1, 39.9
$ February_precipitacion <dbl> 139.3, 12.1, 5.6, 121.1, 71.9
$ March_precipitacion <dbl> 45.2, 17.9, 82.5, 19.1, 5.0
$ April_precipitacion <dbl> 111.7, 6.5, 61.0, 21.8, 27.0
$ May_precipitacion <dbl> 36.1, 73.2, 15.4, 14.7, 145.7
$ June_precipitacion <dbl> 149.1, 72.1, 125.7, 83.5, 42.9
$ July_precipitacion <dbl> 113.1, 131.3, 96.9, 130.4, 105.3
$ August_precipitacion <dbl> 111.5, 137.3, 133.9, 74.5, 139.6
$ September_precipitacion <dbl> 106.2, 148.0, 63.1, 36.2, 59.3
$ October_precipitacion <dbl> 18.9, 4.6, 69.2, 129.6, 21.2
$ November_precipitacion <dbl> 2.9, 100.5, 131.4, 73.3, 122.7
$ December_precipitacion <dbl> 4.0, 18.0, 67.7, 143.9, 140.5
$ January_temperatura <dbl> 16.9, 9.2, 12.7, 23.8, 29.2
$ February_temperatura <dbl> 6.2, 20.3, 22.5, 8.6, 6.2
$ March_temperatura <dbl> 16.1, 9.1, 20.4, 16.5, 28.0
$ April_temperatura <dbl> 17.2, 17.4, 10.8, 34.6, 30.7
$ May_temperatura <dbl> 7.9, 13.5, 33.6, 26.3, 33.8
$ June_temperatura <dbl> 9.3, 13.9, 34.6, 22.6, 27.1
$ July_temperatura <dbl> 17.7, 25.9, 11.0, 8.2, 21.7
$ August_temperatura <dbl> 29.7, 5.1, 7.4, 21.9, 16.5
$ September_temperatura <dbl> 12.2, 10.0, 8.4, 11.4, 29.3
$ October_temperatura <dbl> 28.8, 6.9, 6.7, 15.9, 27.2
$ November_temperatura <dbl> 20.3, 21.6, 26.0, 33.8, 30.6
$ December_temperatura <dbl> 9.3, 26.6, 18.9, 34.6, 10.7
Paso 1: Tabla básica con gt
Comenzamos creando una tabla básica para ver el punto de partida.
# Tabla básica sin formato
tabla_basica <- datos_anchos |>
gt() |>
tab_header(
title = "Datos Hidrológicos Mensuales por Cuenca",
subtitle = "Caudal medio (m³/s), Precipitación (mm) y Temperatura (°C)"
)
tabla_basica| Datos Hidrológicos Mensuales por Cuenca | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Caudal medio (m³/s), Precipitación (mm) y Temperatura (°C) | ||||||||||||||||||||||||||||||||||||
| cuenca | January_caudal_medio | February_caudal_medio | March_caudal_medio | April_caudal_medio | May_caudal_medio | June_caudal_medio | July_caudal_medio | August_caudal_medio | September_caudal_medio | October_caudal_medio | November_caudal_medio | December_caudal_medio | January_precipitacion | February_precipitacion | March_precipitacion | April_precipitacion | May_precipitacion | June_precipitacion | July_precipitacion | August_precipitacion | September_precipitacion | October_precipitacion | November_precipitacion | December_precipitacion | January_temperatura | February_temperatura | March_temperatura | April_temperatura | May_temperatura | June_temperatura | July_temperatura | August_temperatura | September_temperatura | October_temperatura | November_temperatura | December_temperatura |
| Tajo | 420.10 | 167.23 | 343.38 | 352.10 | 233.93 | 353.70 | 213.70 | 158.57 | 439.53 | 68.33 | 451.92 | 477.02 | 16.5 | 139.3 | 45.2 | 111.7 | 36.1 | 149.1 | 113.1 | 111.5 | 106.2 | 18.9 | 2.9 | 4.0 | 16.9 | 6.2 | 16.1 | 17.2 | 7.9 | 9.3 | 17.7 | 29.7 | 12.2 | 28.8 | 20.3 | 9.3 |
| Duero | 354.74 | 262.73 | 230.23 | 422.69 | 64.05 | 432.98 | 74.22 | 154.76 | 33.16 | 64.88 | 343.41 | 426.50 | 18.3 | 12.1 | 17.9 | 6.5 | 73.2 | 72.1 | 131.3 | 137.3 | 148.0 | 4.6 | 100.5 | 18.0 | 9.2 | 20.3 | 9.1 | 17.4 | 13.5 | 13.9 | 25.9 | 5.1 | 10.0 | 6.9 | 21.6 | 26.6 |
| Ebro | 400.70 | 153.23 | 311.47 | 409.64 | 10.26 | 20.35 | 226.15 | 152.24 | 96.34 | 486.96 | 340.83 | 343.67 | 127.7 | 5.6 | 82.5 | 61.0 | 15.4 | 125.7 | 96.9 | 133.9 | 63.1 | 69.2 | 131.4 | 67.7 | 12.7 | 22.5 | 20.4 | 10.8 | 33.6 | 34.6 | 11.0 | 7.4 | 8.4 | 6.7 | 26.0 | 18.9 |
| Guadalquivir | 36.52 | 483.40 | 20.85 | 327.21 | 437.70 | 456.12 | 315.70 | 202.05 | 427.21 | 229.61 | 213.68 | 146.82 | 43.1 | 121.1 | 19.1 | 21.8 | 14.7 | 83.5 | 130.4 | 74.5 | 36.2 | 129.6 | 73.3 | 143.9 | 23.8 | 8.6 | 16.5 | 34.6 | 26.3 | 22.6 | 8.2 | 21.9 | 11.4 | 15.9 | 33.8 | 34.6 |
| Guadiana | 330.63 | 328.74 | 40.05 | 373.13 | 231.95 | 249.85 | 379.08 | 360.77 | 19.75 | 104.04 | 233.65 | 146.32 | 39.9 | 71.9 | 5.0 | 27.0 | 145.7 | 42.9 | 105.3 | 139.6 | 59.3 | 21.2 | 122.7 | 140.5 | 29.2 | 6.2 | 28.0 | 30.7 | 33.8 | 27.1 | 21.7 | 16.5 | 29.3 | 27.2 | 30.6 | 10.7 |
Paso 2: Cambiar a fuente Arial Narrow
La fuente Arial Narrow es ideal para tablas anchas porque permite mostrar más información en menos espacio horizontal.
tabla_fuente <- datos_anchos |>
gt() |>
tab_header(
title = "Datos Hidrológicos Mensuales por Cuenca",
subtitle = "Caudal medio (m³/s), Precipitación (mm) y Temperatura (°C)"
) |>
# Aplicar Arial Narrow a toda la tabla
tab_options(
table.font.names = c("Arial Narrow", "Arial", "sans-serif"),
table.font.size = px(12),
heading.title.font.size = px(16),
heading.subtitle.font.size = px(14),
column_labels.font.size = px(11)
) |>
# Ajustar ancho de columnas
cols_width(
cuenca ~ px(100),
everything() ~ px(65)
)
tabla_fuente| Datos Hidrológicos Mensuales por Cuenca | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Caudal medio (m³/s), Precipitación (mm) y Temperatura (°C) | ||||||||||||||||||||||||||||||||||||
| cuenca | January_caudal_medio | February_caudal_medio | March_caudal_medio | April_caudal_medio | May_caudal_medio | June_caudal_medio | July_caudal_medio | August_caudal_medio | September_caudal_medio | October_caudal_medio | November_caudal_medio | December_caudal_medio | January_precipitacion | February_precipitacion | March_precipitacion | April_precipitacion | May_precipitacion | June_precipitacion | July_precipitacion | August_precipitacion | September_precipitacion | October_precipitacion | November_precipitacion | December_precipitacion | January_temperatura | February_temperatura | March_temperatura | April_temperatura | May_temperatura | June_temperatura | July_temperatura | August_temperatura | September_temperatura | October_temperatura | November_temperatura | December_temperatura |
| Tajo | 420.10 | 167.23 | 343.38 | 352.10 | 233.93 | 353.70 | 213.70 | 158.57 | 439.53 | 68.33 | 451.92 | 477.02 | 16.5 | 139.3 | 45.2 | 111.7 | 36.1 | 149.1 | 113.1 | 111.5 | 106.2 | 18.9 | 2.9 | 4.0 | 16.9 | 6.2 | 16.1 | 17.2 | 7.9 | 9.3 | 17.7 | 29.7 | 12.2 | 28.8 | 20.3 | 9.3 |
| Duero | 354.74 | 262.73 | 230.23 | 422.69 | 64.05 | 432.98 | 74.22 | 154.76 | 33.16 | 64.88 | 343.41 | 426.50 | 18.3 | 12.1 | 17.9 | 6.5 | 73.2 | 72.1 | 131.3 | 137.3 | 148.0 | 4.6 | 100.5 | 18.0 | 9.2 | 20.3 | 9.1 | 17.4 | 13.5 | 13.9 | 25.9 | 5.1 | 10.0 | 6.9 | 21.6 | 26.6 |
| Ebro | 400.70 | 153.23 | 311.47 | 409.64 | 10.26 | 20.35 | 226.15 | 152.24 | 96.34 | 486.96 | 340.83 | 343.67 | 127.7 | 5.6 | 82.5 | 61.0 | 15.4 | 125.7 | 96.9 | 133.9 | 63.1 | 69.2 | 131.4 | 67.7 | 12.7 | 22.5 | 20.4 | 10.8 | 33.6 | 34.6 | 11.0 | 7.4 | 8.4 | 6.7 | 26.0 | 18.9 |
| Guadalquivir | 36.52 | 483.40 | 20.85 | 327.21 | 437.70 | 456.12 | 315.70 | 202.05 | 427.21 | 229.61 | 213.68 | 146.82 | 43.1 | 121.1 | 19.1 | 21.8 | 14.7 | 83.5 | 130.4 | 74.5 | 36.2 | 129.6 | 73.3 | 143.9 | 23.8 | 8.6 | 16.5 | 34.6 | 26.3 | 22.6 | 8.2 | 21.9 | 11.4 | 15.9 | 33.8 | 34.6 |
| Guadiana | 330.63 | 328.74 | 40.05 | 373.13 | 231.95 | 249.85 | 379.08 | 360.77 | 19.75 | 104.04 | 233.65 | 146.32 | 39.9 | 71.9 | 5.0 | 27.0 | 145.7 | 42.9 | 105.3 | 139.6 | 59.3 | 21.2 | 122.7 | 140.5 | 29.2 | 6.2 | 28.0 | 30.7 | 33.8 | 27.1 | 21.7 | 16.5 | 29.3 | 27.2 | 30.6 | 10.7 |
Paso 3: Organizar columnas por categorías
Vamos a agrupar las columnas por tipo de variable para mejorar la legibilidad.
# Reorganizar datos para mejor agrupación
datos_categorias <- datos_hidrologicos |>
select(cuenca, mes, caudal_medio, precipitacion, temperatura) |>
mutate(mes = as.character(mes))
tabla_categorias <- datos_categorias |>
gt(groupname_col = "cuenca") |>
tab_header(
title = "Análisis Hidrológico Mensual",
subtitle = "Principales variables por cuenca hidrográfica"
) |>
# Formato de fuente
tab_options(
table.font.names = c("Arial Narrow", "Arial", "sans-serif"),
table.font.size = px(11),
heading.title.font.size = px(18),
heading.subtitle.font.size = px(14),
row_group.font.weight = "bold",
row_group.background.color = "#E8F4F8"
) |>
# Etiquetas de columnas
cols_label(
mes = "Mes",
caudal_medio = "Caudal (m³/s)",
precipitacion = "Precip. (mm)",
temperatura = "Temp. (°C)"
) |>
# Formato de números
fmt_number(
columns = c(caudal_medio, precipitacion, temperatura),
decimals = 1,
sep_mark = ".",
dec_mark = ","
)
tabla_categorias| Análisis Hidrológico Mensual | |||
|---|---|---|---|
| Principales variables por cuenca hidrográfica | |||
| Mes | Caudal (m³/s) | Precip. (mm) | Temp. (°C) |
| Tajo | |||
| January | 420,1 | 16,5 | 16,9 |
| February | 167,2 | 139,3 | 6,2 |
| March | 343,4 | 45,2 | 16,1 |
| April | 352,1 | 111,7 | 17,2 |
| May | 233,9 | 36,1 | 7,9 |
| June | 353,7 | 149,1 | 9,3 |
| July | 213,7 | 113,1 | 17,7 |
| August | 158,6 | 111,5 | 29,7 |
| September | 439,5 | 106,2 | 12,2 |
| October | 68,3 | 18,9 | 28,8 |
| November | 451,9 | 2,9 | 20,3 |
| December | 477,0 | 4,0 | 9,3 |
| Duero | |||
| January | 354,7 | 18,3 | 9,2 |
| February | 262,7 | 12,1 | 20,3 |
| March | 230,2 | 17,9 | 9,1 |
| April | 422,7 | 6,5 | 17,4 |
| May | 64,0 | 73,2 | 13,5 |
| June | 433,0 | 72,1 | 13,9 |
| July | 74,2 | 131,3 | 25,9 |
| August | 154,8 | 137,3 | 5,1 |
| September | 33,2 | 148,0 | 10,0 |
| October | 64,9 | 4,6 | 6,9 |
| November | 343,4 | 100,5 | 21,6 |
| December | 426,5 | 18,0 | 26,6 |
| Ebro | |||
| January | 400,7 | 127,7 | 12,7 |
| February | 153,2 | 5,6 | 22,5 |
| March | 311,5 | 82,5 | 20,4 |
| April | 409,6 | 61,0 | 10,8 |
| May | 10,3 | 15,4 | 33,6 |
| June | 20,4 | 125,7 | 34,6 |
| July | 226,2 | 96,9 | 11,0 |
| August | 152,2 | 133,9 | 7,4 |
| September | 96,3 | 63,1 | 8,4 |
| October | 487,0 | 69,2 | 6,7 |
| November | 340,8 | 131,4 | 26,0 |
| December | 343,7 | 67,7 | 18,9 |
| Guadalquivir | |||
| January | 36,5 | 43,1 | 23,8 |
| February | 483,4 | 121,1 | 8,6 |
| March | 20,9 | 19,1 | 16,5 |
| April | 327,2 | 21,8 | 34,6 |
| May | 437,7 | 14,7 | 26,3 |
| June | 456,1 | 83,5 | 22,6 |
| July | 315,7 | 130,4 | 8,2 |
| August | 202,1 | 74,5 | 21,9 |
| September | 427,2 | 36,2 | 11,4 |
| October | 229,6 | 129,6 | 15,9 |
| November | 213,7 | 73,3 | 33,8 |
| December | 146,8 | 143,9 | 34,6 |
| Guadiana | |||
| January | 330,6 | 39,9 | 29,2 |
| February | 328,7 | 71,9 | 6,2 |
| March | 40,0 | 5,0 | 28,0 |
| April | 373,1 | 27,0 | 30,7 |
| May | 231,9 | 145,7 | 33,8 |
| June | 249,8 | 42,9 | 27,1 |
| July | 379,1 | 105,3 | 21,7 |
| August | 360,8 | 139,6 | 16,5 |
| September | 19,8 | 59,3 | 29,3 |
| October | 104,0 | 21,2 | 27,2 |
| November | 233,7 | 122,7 | 30,6 |
| December | 146,3 | 140,5 | 10,7 |
Paso 4: Efecto cebra o pijama
Aplicamos diferentes estilos de sombreado para mejorar la legibilidad.
# Versión 1: Cebra simple (filas alternas)
tabla_cebra_simple <- datos_categorias |>
gt(groupname_col = "cuenca") |>
tab_header(
title = "Análisis Hidrológico - Estilo Cebra Simple",
subtitle = "Sombreado en filas alternas"
) |>
# Fuente Arial Narrow
tab_options(
table.font.names = c("Arial Narrow", "Arial", "sans-serif"),
table.font.size = px(11),
row_group.font.weight = "bold",
row_group.background.color = "#2C5F7C",
) |>
# Usar tab_style() para el color del texto:
tab_style(
style = cell_text(color = "white"),
locations = cells_row_groups() # ✅ Aplicar a los grupos de filas
) |>
# Efecto cebra en filas pares
tab_style(
style = cell_fill(color = "#F0F8FC"),
locations = cells_body(
rows = seq(2, nrow(datos_categorias), 2)
)
) |>
cols_label(
mes = "Mes",
caudal_medio = "Caudal (m³/s)",
precipitacion = "Precip. (mm)",
temperatura = "Temp. (°C)"
) |>
fmt_number(
columns = c(caudal_medio, precipitacion, temperatura),
decimals = 1
)
tabla_cebra_simple| Análisis Hidrológico - Estilo Cebra Simple | |||
|---|---|---|---|
| Sombreado en filas alternas | |||
| Mes | Caudal (m³/s) | Precip. (mm) | Temp. (°C) |
| Tajo | |||
| January | 420.1 | 16.5 | 16.9 |
| February | 167.2 | 139.3 | 6.2 |
| March | 343.4 | 45.2 | 16.1 |
| April | 352.1 | 111.7 | 17.2 |
| May | 233.9 | 36.1 | 7.9 |
| June | 353.7 | 149.1 | 9.3 |
| July | 213.7 | 113.1 | 17.7 |
| August | 158.6 | 111.5 | 29.7 |
| September | 439.5 | 106.2 | 12.2 |
| October | 68.3 | 18.9 | 28.8 |
| November | 451.9 | 2.9 | 20.3 |
| December | 477.0 | 4.0 | 9.3 |
| Duero | |||
| January | 354.7 | 18.3 | 9.2 |
| February | 262.7 | 12.1 | 20.3 |
| March | 230.2 | 17.9 | 9.1 |
| April | 422.7 | 6.5 | 17.4 |
| May | 64.0 | 73.2 | 13.5 |
| June | 433.0 | 72.1 | 13.9 |
| July | 74.2 | 131.3 | 25.9 |
| August | 154.8 | 137.3 | 5.1 |
| September | 33.2 | 148.0 | 10.0 |
| October | 64.9 | 4.6 | 6.9 |
| November | 343.4 | 100.5 | 21.6 |
| December | 426.5 | 18.0 | 26.6 |
| Ebro | |||
| January | 400.7 | 127.7 | 12.7 |
| February | 153.2 | 5.6 | 22.5 |
| March | 311.5 | 82.5 | 20.4 |
| April | 409.6 | 61.0 | 10.8 |
| May | 10.3 | 15.4 | 33.6 |
| June | 20.4 | 125.7 | 34.6 |
| July | 226.2 | 96.9 | 11.0 |
| August | 152.2 | 133.9 | 7.4 |
| September | 96.3 | 63.1 | 8.4 |
| October | 487.0 | 69.2 | 6.7 |
| November | 340.8 | 131.4 | 26.0 |
| December | 343.7 | 67.7 | 18.9 |
| Guadalquivir | |||
| January | 36.5 | 43.1 | 23.8 |
| February | 483.4 | 121.1 | 8.6 |
| March | 20.9 | 19.1 | 16.5 |
| April | 327.2 | 21.8 | 34.6 |
| May | 437.7 | 14.7 | 26.3 |
| June | 456.1 | 83.5 | 22.6 |
| July | 315.7 | 130.4 | 8.2 |
| August | 202.1 | 74.5 | 21.9 |
| September | 427.2 | 36.2 | 11.4 |
| October | 229.6 | 129.6 | 15.9 |
| November | 213.7 | 73.3 | 33.8 |
| December | 146.8 | 143.9 | 34.6 |
| Guadiana | |||
| January | 330.6 | 39.9 | 29.2 |
| February | 328.7 | 71.9 | 6.2 |
| March | 40.0 | 5.0 | 28.0 |
| April | 373.1 | 27.0 | 30.7 |
| May | 231.9 | 145.7 | 33.8 |
| June | 249.8 | 42.9 | 27.1 |
| July | 379.1 | 105.3 | 21.7 |
| August | 360.8 | 139.6 | 16.5 |
| September | 19.8 | 59.3 | 29.3 |
| October | 104.0 | 21.2 | 27.2 |
| November | 233.7 | 122.7 | 30.6 |
| December | 146.3 | 140.5 | 10.7 |
Paso 5: Efecto cebra en intervalo específico
Aplicamos el efecto cebra solo a un rango determinado de filas y añadimos resaltado condicional.
# Preparar datos con resumen
datos_con_resumen <- datos_hidrologicos |>
group_by(cuenca) |>
summarise(
caudal_anual = mean(caudal_medio, na.rm = TRUE),
precip_anual = sum(precipitacion, na.rm = TRUE),
temp_media = mean(temperatura, na.rm = TRUE),
.groups = "drop"
) |>
arrange(desc(caudal_anual))
tabla_cebra_intervalo <- datos_con_resumen |>
gt() |>
tab_header(
title = "Resumen Anual por Cuenca",
subtitle = "Efecto cebra aplicado a intervalo específico (filas 2-4)"
) |>
# Configuración de fuente
tab_options(
table.font.names = c("Arial Narrow", "Arial", "sans-serif"),
table.font.size = px(12),
heading.title.font.size = px(16),
heading.subtitle.font.size = px(14)
) |>
# Etiquetas
cols_label(
cuenca = "Cuenca",
caudal_anual = "Caudal Medio Anual (m³/s)",
precip_anual = "Precipitación Total (mm)",
temp_media = "Temperatura Media (°C)"
) |>
# Formato de números
fmt_number(
columns = c(caudal_anual, precip_anual, temp_media),
decimals = 1,
sep_mark = ".",
dec_mark = ","
) |>
# Efecto cebra solo en filas 2 a 4
tab_style(
style = cell_fill(color = "#E8F4F8"),
locations = cells_body(rows = c(2, 4))
) |>
# Resaltar valores máximos
tab_style(
style = list(
cell_fill(color = "#FFE5B4"),
cell_text(weight = "bold")
),
locations = cells_body(
columns = caudal_anual,
rows = caudal_anual == max(caudal_anual)
)
)
tabla_cebra_intervalo| Resumen Anual por Cuenca | |||
|---|---|---|---|
| Efecto cebra aplicado a intervalo específico (filas 2-4) | |||
| Cuenca | Caudal Medio Anual (m³/s) | Precipitación Total (mm) | Temperatura Media (°C) |
| Tajo | 306,6 | 854,5 | 16,0 |
| Guadalquivir | 274,7 | 891,2 | 21,5 |
| Ebro | 246,0 | 980,1 | 17,8 |
| Duero | 238,7 | 739,8 | 15,0 |
| Guadiana | 233,2 | 921,0 | 24,2 |
Paso 6: Tabla avanzada con múltiples mejoras
Combinamos todas las técnicas anteriores y añadimos elementos adicionales.
# Crear datos más complejos para demostración
datos_completos <- datos_hidrologicos |>
group_by(cuenca, trimestre = quarter(match(mes, month.name))) |>
summarise(
caudal_medio = mean(caudal_medio, na.rm = TRUE),
caudal_max_trim = max(caudal_max, na.rm = TRUE),
caudal_min_trim = min(caudal_min, na.rm = TRUE),
precipitacion = sum(precipitacion, na.rm = TRUE),
temperatura = mean(temperatura, na.rm = TRUE),
evaporacion = sum(evaporacion, na.rm = TRUE),
nivel_embalse = mean(nivel_embalse, na.rm = TRUE),
.groups = "drop"
) |>
mutate(
trimestre = paste0("T", trimestre),
balance_hidrico = precipitacion - evaporacion,
indice_sequia = case_when(
balance_hidrico < -100 ~ "Sequía severa",
balance_hidrico < 0 ~ "Déficit",
balance_hidrico < 100 ~ "Normal",
TRUE ~ "Excedente"
)
)
tabla_avanzada <- datos_completos |>
gt(groupname_col = "cuenca") |>
# Encabezado
tab_header(
title = md("**Sistema de Información Hidrológica**"),
subtitle = md("*Análisis trimestral con indicadores de gestión*")
) |>
# Spanners para agrupar columnas relacionadas
tab_spanner(
label = "CAUDALES (m³/s)",
columns = c(caudal_medio, caudal_max_trim, caudal_min_trim)
) |>
tab_spanner(
label = "BALANCE HÍDRICO",
columns = c(precipitacion, evaporacion, balance_hidrico)
) |>
tab_spanner(
label = "INDICADORES",
columns = c(nivel_embalse, indice_sequia)
) |>
# Etiquetas personalizadas
cols_label(
trimestre = "Periodo",
caudal_medio = "Media",
caudal_max_trim = "Máx",
caudal_min_trim = "Mín",
precipitacion = "P (mm)",
evaporacion = "E (mm)",
balance_hidrico = "P-E",
temperatura = "T (°C)",
nivel_embalse = "Embalse (%)",
indice_sequia = "Estado"
) |>
# Formato de números
fmt_number(
columns = c(caudal_medio, caudal_max_trim, caudal_min_trim,
precipitacion, evaporacion, balance_hidrico,
temperatura, nivel_embalse),
decimals = 1,
sep_mark = ".",
dec_mark = ","
) |>
# Ocultar columna de temperatura (ejemplo de optimización)
cols_hide(columns = temperatura) |>
# Estilos y colores
tab_options(
table.font.names = c("Arial Narrow", "Arial", "sans-serif"),
table.font.size = px(11),
heading.title.font.size = px(18),
heading.subtitle.font.size = px(14),
heading.background.color = "#1E3A5F",
column_labels.background.color = "#4A7BA7",
column_labels.font.weight = "bold",
row_group.background.color = "#2C5F7C",
row_group.font.weight = "bold",
table.border.top.width = px(3),
table.border.top.color = "#1E3A5F",
table.border.bottom.width = px(3),
table.border.bottom.color = "#1E3A5F"
) |>
tab_style(
style = cell_text(color = "white"),
locations = cells_title(groups = c("title", "subtitle"))
) |>
tab_style(
style = cell_text(color = "white"),
locations = cells_column_labels()
) |>
# Efecto cebra en todas las filas de datos
tab_style(
style = cell_fill(color = "#F5FBFF"),
locations = cells_body(rows = seq(2, nrow(datos_completos), 2))
) |>
# Colorear según el índice de sequía
tab_style(
style = list(
cell_fill(color = "#FFD6D6"),
cell_text(weight = "bold", color = "#8B0000")
),
locations = cells_body(
columns = indice_sequia,
rows = indice_sequia == "Sequía severa"
)
) |>
tab_style(
style = list(
cell_fill(color = "#FFF4E6"),
cell_text(color = "#CC6600")
),
locations = cells_body(
columns = indice_sequia,
rows = indice_sequia == "Déficit"
)
) |>
tab_style(
style = list(
cell_fill(color = "#E6F7E6"),
cell_text(color = "#006400")
),
locations = cells_body(
columns = indice_sequia,
rows = indice_sequia == "Excedente"
)
) |>
# Resaltar valores extremos de caudal
tab_style(
style = list(
cell_text(weight = "bold", color = "#0066CC")
),
locations = cells_body(
columns = caudal_max_trim,
rows = caudal_max_trim > quantile(caudal_max_trim, 0.9)
)
) |>
# Nota al pie
tab_footnote(
footnote = "P: Precipitación, E: Evapotranspiración, P-E: Balance hídrico",
locations = cells_column_spanners(spanners = "BALANCE HÍDRICO")
) |>
tab_footnote(
footnote = "Datos simulados para demostración",
locations = cells_title(groups = "title")
)
tabla_avanzada| Sistema de Información Hidrológica1 | ||||||||
|---|---|---|---|---|---|---|---|---|
| Análisis trimestral con indicadores de gestión | ||||||||
| Periodo |
CAUDALES (m³/s)
|
BALANCE HÍDRICO2
|
INDICADORES
|
|||||
| Media | Máx | Mín | P (mm) | E (mm) | P-E | Embalse (%) | Estado | |
| Duero | ||||||||
| T1 | 282,6 | 716,6 | 110,0 | 48,3 | 277,9 | −229,6 | 56,6 | Sequía severa |
| T2 | 306,6 | 896,1 | 41,0 | 151,8 | 266,8 | −115,0 | 50,4 | Sequía severa |
| T3 | 87,4 | 230,6 | 23,0 | 416,6 | 319,5 | 97,1 | 54,1 | Normal |
| T4 | 278,3 | 635,3 | 31,1 | 123,1 | 389,5 | −266,4 | 54,9 | Sequía severa |
| Ebro | ||||||||
| T1 | 288,5 | 841,5 | 122,6 | 215,8 | 353,4 | −137,6 | 73,1 | Sequía severa |
| T2 | 146,8 | 655,4 | 6,1 | 202,1 | 300,8 | −98,7 | 71,4 | Déficit |
| T3 | 158,2 | 434,2 | 73,2 | 293,9 | 347,2 | −53,3 | 68,8 | Déficit |
| T4 | 390,5 | 739,6 | 178,7 | 268,3 | 268,3 | 0,0 | 66,5 | Normal |
| Guadalquivir | ||||||||
| T1 | 180,3 | 899,1 | 11,5 | 183,3 | 504,6 | −321,3 | 71,6 | Sequía severa |
| T2 | 407,0 | 944,2 | 124,3 | 120,0 | 359,3 | −239,3 | 76,6 | Sequía severa |
| T3 | 315,0 | 657,9 | 76,8 | 241,1 | 389,0 | −147,9 | 71,0 | Sequía severa |
| T4 | 196,7 | 521,2 | 68,4 | 346,8 | 277,5 | 69,3 | 56,1 | Normal |
| Guadiana | ||||||||
| T1 | 233,1 | 736,4 | 29,2 | 116,8 | 390,5 | −273,7 | 68,1 | Sequía severa |
| T2 | 285,0 | 750,0 | 118,3 | 215,6 | 411,5 | −195,9 | 54,0 | Sequía severa |
| T3 | 253,2 | 855,0 | 9,9 | 304,2 | 308,2 | −4,0 | 77,1 | Déficit |
| T4 | 161,3 | 427,6 | 31,2 | 284,4 | 360,5 | −76,1 | 54,7 | Déficit |
| Tajo | ||||||||
| T1 | 310,2 | 576,9 | 55,2 | 201,0 | 258,5 | −57,5 | 60,9 | Déficit |
| T2 | 313,2 | 799,4 | 109,6 | 296,9 | 345,8 | −48,9 | 78,7 | Déficit |
| T3 | 270,6 | 703,2 | 112,6 | 330,8 | 334,5 | −3,7 | 55,7 | Déficit |
| T4 | 332,4 | 926,4 | 54,7 | 25,8 | 238,0 | −212,2 | 81,5 | Sequía severa |
| 1 Datos simulados para demostración | ||||||||
| 2 P: Precipitación, E: Evapotranspiración, P-E: Balance hídrico | ||||||||
Paso 7: Técnicas adicionales para tablas muy anchas
Para tablas extremadamente anchas, aquí hay técnicas adicionales:
# Crear una tabla muy ancha con datos mensuales completos
datos_muy_anchos <- datos_hidrologicos |>
filter(str_detect(estacion, "EA001|EA002")) |>
select(cuenca, mes, caudal_medio, precipitacion) |>
pivot_wider(
names_from = mes,
values_from = c(caudal_medio, precipitacion),
names_glue = "{mes}_{.value}"
)
tabla_optimizada <- datos_muy_anchos |>
gt() |>
tab_header(
title = "Optimización para Tablas Muy Anchas",
subtitle = "Técnicas de compresión visual"
) |>
# Configuración extrema para ahorro de espacio
tab_options(
table.font.names = c("Arial Narrow", "Helvetica Narrow", "sans-serif"),
table.font.size = px(9),
data_row.padding = px(2), # Reducir padding
column_labels.font.size = px(8),
column_labels.padding = px(3),
heading.title.font.size = px(14),
heading.subtitle.font.size = px(11)
) |>
# Ancho mínimo de columnas
cols_width(
cuenca ~ px(80),
everything() ~ px(45)
) |>
# Rotar etiquetas de columnas para ahorrar espacio horizontal
tab_style(
style = css(transform = "rotate(-45deg)",
"white-space" = "nowrap",
"text-align" = "left"),
locations = cells_column_labels(
columns = -cuenca
)
) |>
# Formato compacto de números
fmt_number(
columns = -cuenca,
decimals = 0,
suffixing = TRUE # Usar notación K, M para números grandes
) |>
# Colores alternados por grupos de columnas
tab_style(
style = cell_fill(color = "#E8F0FE"),
locations = cells_body(
columns = contains("January") | contains("March") |
contains("May") | contains("July") |
contains("September") | contains("November")
)
) |>
tab_style(
style = cell_fill(color = "#FFF3E0"),
locations = cells_body(
columns = contains("February") | contains("April") |
contains("June") | contains("August") |
contains("October") | contains("December")
)
)
tabla_optimizada| Optimización para Tablas Muy Anchas | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Técnicas de compresión visual | ||||||||||||||||||||||||
| cuenca | January_caudal_medio | February_caudal_medio | March_caudal_medio | April_caudal_medio | May_caudal_medio | June_caudal_medio | July_caudal_medio | August_caudal_medio | September_caudal_medio | October_caudal_medio | November_caudal_medio | December_caudal_medio | January_precipitacion | February_precipitacion | March_precipitacion | April_precipitacion | May_precipitacion | June_precipitacion | July_precipitacion | August_precipitacion | September_precipitacion | October_precipitacion | November_precipitacion | December_precipitacion |
| Tajo | 420 | 167 | 343 | 352 | 234 | 354 | 214 | 159 | 440 | 68 | 452 | 477 | 16 | 139 | 45 | 112 | 36 | 149 | 113 | 112 | 106 | 19 | 3 | 4 |
| Duero | 355 | 263 | 230 | 423 | 64 | 433 | 74 | 155 | 33 | 65 | 343 | 426 | 18 | 12 | 18 | 6 | 73 | 72 | 131 | 137 | 148 | 5 | 100 | 18 |
Paso 8: Función personalizada para aplicar estilos
Creamos una función reutilizable para aplicar nuestros estilos preferidos.
# Función para aplicar estilo hidrológico estándar
aplicar_estilo_hidrologico <- function(tabla_gt,
efecto_cebra = TRUE,
filas_cebra = "pares",
fuente = "Arial Narrow",
tamano_fuente = 11) {
# Aplicar configuración base
tabla_estilizada <- tabla_gt |>
tab_options(
table.font.names = c(fuente, "Arial", "sans-serif"),
table.font.size = px(tamano_fuente),
heading.title.font.size = px(tamano_fuente + 5),
heading.subtitle.font.size = px(tamano_fuente + 2),
heading.background.color = "#1E3A5F",
column_labels.background.color = "#4A7BA7",
column_labels.font.weight = "bold",
table.border.top.width = px(2),
table.border.top.color = "#1E3A5F"
) |>
tab_style(
style = cell_text(color = "white"),
locations = cells_title(groups = c("title", "subtitle"))
) |>
tab_style(
style = cell_text(color = "white"),
locations = cells_column_labels()
)
n_filas <- tabla_gt$`_data` |> nrow()
# Aplicar efecto cebra si está activado
if (efecto_cebra) {
if (all(filas_cebra == "pares")) {
filas_a_colorear <- seq(2, n_filas * 2, 2) # toma el número de filas. Multiplico por 2 por asegurar en caso de encabezados de grupo
} else if (all(filas_cebra == "impares")) {
filas_a_colorear <- seq(1, n_filas * 2, 2)
} else if (is.numeric(filas_cebra)) {
filas_a_colorear <- filas_cebra
}
tabla_estilizada <- tabla_estilizada |>
tab_style(
style = cell_fill(color = "#F0F8FC"),
locations = cells_body(rows = filas_a_colorear)
)
}
return(tabla_estilizada)
}
# Ejemplo de uso de la función
datos_ejemplo <- datos_hidrologicos |>
filter(mes %in% c("January", "February", "March")) |>
group_by(cuenca) |>
summarise(
caudal_medio = mean(caudal_medio),
precipitacion = sum(precipitacion),
temperatura = mean(temperatura),
.groups = "drop"
)
tabla_con_funcion <- datos_ejemplo |>
gt() |>
tab_header(
title = "Tabla con Estilo Personalizado",
subtitle = "Usando función reutilizable"
) |>
cols_label(
cuenca = "Cuenca",
caudal_medio = "Q medio (m³/s)",
precipitacion = "P total (mm)",
temperatura = "T media (°C)"
) |>
fmt_number(
columns = where(is.numeric),
decimals = 1,
sep_mark = ".",
dec_mark = ","
) |>
aplicar_estilo_hidrologico(
efecto_cebra = TRUE,
filas_cebra = c(1, 3, 5), # Solo filas impares
tamano_fuente = 10
)
tabla_con_funcion| Tabla con Estilo Personalizado | |||
|---|---|---|---|
| Usando función reutilizable | |||
| Cuenca | Q medio (m³/s) | P total (mm) | T media (°C) |
| Duero | 282,6 | 48,3 | 12,9 |
| Ebro | 288,5 | 215,8 | 18,5 |
| Guadalquivir | 180,3 | 183,3 | 16,3 |
| Guadiana | 233,1 | 116,8 | 21,1 |
| Tajo | 310,2 | 201,0 | 13,1 |
Consejos finales para tablas anchas
1. Optimización del espacio horizontal
- Usar fuentes condensadas (Arial Narrow, Helvetica Narrow)
- Reducir el padding de las celdas
- Abreviar nombres de columnas cuando sea posible
- Considerar transponer la tabla si tiene pocas filas y muchas columnas
2. Mejora de la legibilidad
- Aplicar efectos cebra para distinguir filas
- Usar colores sutiles para agrupar columnas relacionadas
- Implementar bordes verticales solo cuando sea necesario
- Destacar valores importantes con formato condicional
3. Organización de la información
- Agrupar columnas relacionadas con
tab_spanner() - Usar filas de grupo para categorizar datos
- Ocultar columnas menos importantes con
cols_hide() - Considerar crear múltiples tablas más pequeñas en lugar de una muy ancha
4. Exportación y visualización
# Guardar como HTML
gtsave(tabla_avanzada, "tabla_hidrologica.html")
# Guardar como imagen PNG (requiere webshot2)
# install.packages("webshot2")
# webshot2::install_chromote()
gtsave(tabla_avanzada, "tabla_hidrologica.png",
expand = 10) # Margen adicional
# Guardar como Word (a través de flextable)
# library(flextable)
# tabla_avanzada |>
# as_flex_table() |>
# save_as_docx(path = "tabla_hidrologica.docx")Ejemplo integrado: Dashboard de cuenca
Para finalizar, aquí hay un ejemplo que combina todas las técnicas para crear una tabla tipo dashboard:
# Preparar datos de resumen ejecutivo
resumen_cuencas <- datos_hidrologicos |>
group_by(cuenca) |>
summarise(
q_medio_anual = mean(caudal_medio),
q_max_anual = max(caudal_max),
q_min_anual = min(caudal_min),
p_total = sum(precipitacion),
t_media = mean(temperatura),
nivel_medio = mean(nivel_embalse),
meses_sequia = sum(precipitacion < 20),
.groups = "drop"
) |>
mutate(
estado = case_when(
nivel_medio > 70 ~ "Óptimo",
nivel_medio > 50 ~ "Normal",
nivel_medio > 30 ~ "Alerta",
TRUE ~ "Crítico"
),
tendencia = sample(c("↑", "↓", "→"), n(), replace = TRUE)
)
dashboard_final <- resumen_cuencas |>
gt() |>
tab_header(
title = md("**DASHBOARD HIDROLÓGICO ANUAL**"),
subtitle = md("*Sistema integrado de monitoreo de cuencas - Año 2024*")
) |>
tab_spanner(
label = md("**CAUDALES** (m³/s)"),
columns = c(q_medio_anual, q_max_anual, q_min_anual)
) |>
tab_spanner(
label = md("**METEOROLOGÍA**"),
columns = c(p_total, t_media)
) |>
tab_spanner(
label = md("**GESTIÓN**"),
columns = c(nivel_medio, meses_sequia, estado, tendencia)
) |>
cols_label(
cuenca = "",
q_medio_anual = "Media",
q_max_anual = "Máximo",
q_min_anual = "Mínimo",
p_total = "P anual (mm)",
t_media = "T media (°C)",
nivel_medio = "Embalse (%)",
meses_sequia = "Meses sequía",
estado = "Estado",
tendencia = "Tend."
) |>
# Formato de números
fmt_number(
columns = c(q_medio_anual, q_max_anual, q_min_anual, p_total, t_media, nivel_medio),
decimals = 1,
sep_mark = ".",
dec_mark = ","
) |>
# Estilos base
tab_options(
table.font.names = c("Arial Narrow", "Arial", "sans-serif"),
table.font.size = px(11),
heading.title.font.size = px(20),
heading.subtitle.font.size = px(14),
heading.background.color = "#0D47A1",
heading.padding = px(10),
column_labels.background.color = "#1976D2",
column_labels.font.weight = "bold",
column_labels.padding = px(8),
data_row.padding = px(5),
table.border.top.width = px(3),
table.border.top.color = "#0D47A1",
table.border.bottom.width = px(3),
table.border.bottom.color = "#0D47A1"
) |>
tab_style(
style = cell_text(color = "white"),
locations = cells_title(groups = c("title", "subtitle"))
) |>
tab_style(
style = cell_text(color = "white"),
locations = cells_column_labels()
) |>
# Efecto cebra sutil
tab_style(
style = cell_fill(color = "#F5F9FF"),
locations = cells_body(rows = seq(2, nrow(resumen_cuencas), 2))
) |>
# Colorear columna de estado
tab_style(
style = list(
cell_fill(color = "#C8E6C9"),
cell_text(weight = "bold", color = "#1B5E20")
),
locations = cells_body(
columns = estado,
rows = estado == "Óptimo"
)
) |>
tab_style(
style = list(
cell_fill(color = "#FFF9C4"),
cell_text(color = "#F57C00")
),
locations = cells_body(
columns = estado,
rows = estado == "Normal"
)
) |>
tab_style(
style = list(
cell_fill(color = "#FFE0B2"),
cell_text(weight = "bold", color = "#E65100")
),
locations = cells_body(
columns = estado,
rows = estado == "Alerta"
)
) |>
tab_style(
style = list(
cell_fill(color = "#FFCDD2"),
cell_text(weight = "bold", color = "#B71C1C")
),
locations = cells_body(
columns = estado,
rows = estado == "Crítico"
)
) |>
# Resaltar valores extremos
tab_style(
style = list(
cell_text(color = "#0D47A1", weight = "bold")
),
locations = cells_body(
columns = q_max_anual,
rows = q_max_anual == max(q_max_anual)
)
) |>
tab_style(
style = list(
cell_text(color = "#B71C1C", weight = "bold")
),
locations = cells_body(
columns = meses_sequia,
rows = meses_sequia > 3
)
) |>
# Notas al pie
tab_footnote(
footnote = md("**Nota:** Datos actualizados al último día del mes"),
locations = cells_title(groups = "subtitle")
) |>
tab_source_note(
source_note = md("*Fuente: Sistema Nacional de Información Hidrológica | Procesado con R + gt*")
)
dashboard_final| DASHBOARD HIDROLÓGICO ANUAL | |||||||||
| Sistema integrado de monitoreo de cuencas - Año 20241 | |||||||||
|
CAUDALES (m³/s)
|
METEOROLOGÍA
|
GESTIÓN
|
|||||||
|---|---|---|---|---|---|---|---|---|---|
| Media | Máximo | Mínimo | P anual (mm) | T media (°C) | Embalse (%) | Meses sequía | Estado | Tend. | |
| Duero | 238,7 | 896,1 | 23,0 | 739,8 | 15,0 | 54,0 | 6 | Normal | → |
| Ebro | 246,0 | 841,5 | 6,1 | 980,1 | 17,8 | 70,0 | 2 | Normal | → |
| Guadalquivir | 274,7 | 944,2 | 11,5 | 891,2 | 21,5 | 68,8 | 2 | Normal | ↑ |
| Guadiana | 233,2 | 855,0 | 9,9 | 921,0 | 24,2 | 63,5 | 1 | Normal | → |
| Tajo | 306,6 | 926,4 | 54,7 | 854,5 | 16,0 | 69,2 | 4 | Normal | → |
| Fuente: Sistema Nacional de Información Hidrológica | Procesado con R + gt | |||||||||
| 1 Nota: Datos actualizados al último día del mes | |||||||||
Conclusión
El paquete gt ofrece una amplia gama de opciones para optimizar la presentación de tablas anchas. Las técnicas clave incluyen:
- Tipografía condensada para maximizar el uso del espacio
- Agrupación lógica de columnas y filas
- Efectos visuales como el sombreado cebra para mejorar la legibilidad
- Formato condicional para destacar información crítica
- Personalización avanzada mediante funciones reutilizables
Estas herramientas son especialmente valiosas en el contexto de la gestión hidrológica, donde frecuentemente trabajamos con series temporales extensas y múltiples variables que requieren una presentación clara y profesional.
Tutorial desarrollado para la aplicación de ciencia de datos en hidrología y gestión de recursos hídricos.