library(tidyverse)
library(gt)
library(gtExtras)
En este post veremos un paso a paso de cómo generar una tabla “con estilo” ✨ usando las librerias gt
y gtExtra
. Esta tabla la diseñé para una infografía que resumen y muestra datos del sistema educativo en Córdoba Capital en el 2023 y acompaña a otras visualizaciones que no se verán en esta mini guía.
Librerias utilizadas
Cargamos las librerias necesarias, en este caso usaremos solamente las siguientes:
Datos
Usaremos datos provenientes del relevamiento anual para establecimientos educativos de la provincia de Córdoba, procesados previamente (por mí) y disponibles para descargar en .csv
:
<- read_csv("data/datos_se_2023.csv")
data
data
# A tibble: 10 × 11
Modalidad Nivel UE_Total UE_Estatal UE_Privado ALUM_Total ALUM_Estatal
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Común Inic… 1757 1444 313 132342 96631
2 Común Prim… 2042 1724 318 354360 256150
3 Común Secu… 932 517 415 346705 208603
4 Común Supe… 207 83 124 76736 45014
5 Especial Todo… 101 60 41 5019 2765
6 Hospitalaria y … Todo… 3 2 1 396 386
7 Jóvenes y Adult… Prim… 178 177 1 4560 4543
8 Jóvenes y Adult… Secu… 136 111 25 38332 33425
9 Artística <NA> 33 28 5 9700 8659
10 Formación Profe… <NA> 83 83 0 32623 32623
# ℹ 4 more variables: ALUM_Privado <dbl>, PD_Total <dbl>, PD_Estatal <dbl>,
# PD_Privado <dbl>
Objetivo
El objetivo será generar la siguiente tabla
Construcción de tabla
Antes de arrancar vamos a definir algunos valores constantes.
<- 32
img_height
<- "<div style='line-height:21px'>" div_total_pct_text
El primer paso será agregar algunas columnas, limpiar o corregir otras:
<- data |>
tabla1 mutate(Nivel = case_when(
is.na(Nivel) ~ "",
TRUE ~ Nivel
|>
)) mutate(
UE_Estatal = as.numeric(UE_Estatal)
|>
) mutate(
Modalidad = case_when(
== "Hospitalaria y Domiciliaria" ~ "Hospitalaria y <br>Domiciliaria",
Modalidad == "Jóvenes y Adultos" ~ "Jóvenes y<br>Adultos",
Modalidad == "Formación Profesional" ~ "Formación<br>Profesional",
Modalidad TRUE ~ Modalidad
)|>
) rowwise() |>
mutate(
#percents_ue = pmap(list(UE_Estatal,UE_Privado,UE_Total), ~c((..1/..3),(..2/..3))),
percents_ue = UE_Estatal/UE_Total,
percents_ue2 = UE_Privado/UE_Total,
UE_Estatal = if_else(UE_Estatal > 0,
str_c(div_total_pct_text, scales::label_comma(big.mark = ".", accuracy = 1)(UE_Estatal),"<br><i>(",scales::label_percent()(percents_ue),")</i></div>"), ""),
UE_Privado = if_else(UE_Privado > 0, str_c(div_total_pct_text, scales::label_comma(big.mark = ".", accuracy = 1)(UE_Privado),"<br><i>(",scales::label_percent()(percents_ue2),")</i></div>"), ""),
#percents_alu = pmap(list(ALUM_Estatal,ALUM_Privado,ALUM_Total), ~c((..1/..3),(..2/..3))),
percents_alu = ALUM_Estatal/ALUM_Total,
percents_alu2 = ALUM_Privado/ALUM_Total,
ALUM_Estatal = if_else(ALUM_Estatal > 0,
str_c(div_total_pct_text, scales::label_comma(big.mark = ".", accuracy = 1)(ALUM_Estatal),"<br><i>(",scales::label_percent()(percents_alu),")</i></div>"), ""),
ALUM_Privado = if_else(ALUM_Privado > 0,
str_c(div_total_pct_text, scales::label_comma(big.mark = ".", accuracy = 1)(ALUM_Privado),"<br><i>(",scales::label_percent()(percents_alu2),")</i></div>"), ""),
#percents_pd = pmap(list(PD_Estatal,PD_Privado,PD_Total), ~c((..1/..3),(..2/..3)))
percents_pd = PD_Estatal/PD_Total,
percents_pd2 = PD_Privado/PD_Total,
PD_Estatal = if_else(PD_Estatal > 0,
str_c(div_total_pct_text, scales::label_comma(big.mark = ".", accuracy = 1)(PD_Estatal),"<br><i>(",scales::label_percent()(percents_pd),")</i></div>"), ""),
PD_Privado = if_else(PD_Privado > 0,
str_c(div_total_pct_text, scales::label_comma(big.mark = ".", accuracy = 1)(PD_Privado),"<br><i>(",scales::label_percent()(percents_pd2),")</i></div>"), "")
|>
) gt(id = "tabla")
tabla1
Modalidad | Nivel | UE_Total | UE_Estatal | UE_Privado | ALUM_Total | ALUM_Estatal | ALUM_Privado | PD_Total | PD_Estatal | PD_Privado | percents_ue | percents_ue2 | percents_alu | percents_alu2 | percents_pd | percents_pd2 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Común | Inicial | 1757 | <div style='line-height:21px'>1.444<br><i>(82%)</i></div> | <div style='line-height:21px'>313<br><i>(18%)</i></div> | 132342 | <div style='line-height:21px'>96.631<br><i>(73%)</i></div> | <div style='line-height:21px'>35.711<br><i>(27%)</i></div> | 10512 | <div style='line-height:21px'>6.768<br><i>(64%)</i></div> | <div style='line-height:21px'>3.744<br><i>(36%)</i></div> | 0.8218554 | 0.178144565 | 0.7301612 | 0.26983875 | 0.6438356 | 0.356164384 |
Común | Primario | 2042 | <div style='line-height:21px'>1.724<br><i>(84%)</i></div> | <div style='line-height:21px'>318<br><i>(16%)</i></div> | 354360 | <div style='line-height:21px'>256.150<br><i>(72%)</i></div> | <div style='line-height:21px'>98.210<br><i>(28%)</i></div> | 31420 | <div style='line-height:21px'>23.544<br><i>(75%)</i></div> | <div style='line-height:21px'>7.876<br><i>(25%)</i></div> | 0.8442703 | 0.155729677 | 0.7228525 | 0.27714753 | 0.7493316 | 0.250668364 |
Común | Secundario | 932 | <div style='line-height:21px'>517<br><i>(55%)</i></div> | <div style='line-height:21px'>415<br><i>(45%)</i></div> | 346705 | <div style='line-height:21px'>208.603<br><i>(60%)</i></div> | <div style='line-height:21px'>138.102<br><i>(40%)</i></div> | 60133 | <div style='line-height:21px'>40.415<br><i>(67%)</i></div> | <div style='line-height:21px'>19.718<br><i>(33%)</i></div> | 0.5547210 | 0.445278970 | 0.6016729 | 0.39832711 | 0.6720935 | 0.327906474 |
Común | Superior | 207 | <div style='line-height:21px'>83<br><i>(40%)</i></div> | <div style='line-height:21px'>124<br><i>(60%)</i></div> | 76736 | <div style='line-height:21px'>45.014<br><i>(59%)</i></div> | <div style='line-height:21px'>31.722<br><i>(41%)</i></div> | 10159 | <div style='line-height:21px'>5.525<br><i>(54%)</i></div> | <div style='line-height:21px'>4.634<br><i>(46%)</i></div> | 0.4009662 | 0.599033816 | 0.5866086 | 0.41339137 | 0.5438527 | 0.456147259 |
Especial | Todos los niveles | 101 | <div style='line-height:21px'>60<br><i>(59%)</i></div> | <div style='line-height:21px'>41<br><i>(41%)</i></div> | 5019 | <div style='line-height:21px'>2.765<br><i>(55%)</i></div> | <div style='line-height:21px'>2.254<br><i>(45%)</i></div> | 2764 | <div style='line-height:21px'>1.827<br><i>(66%)</i></div> | <div style='line-height:21px'>937<br><i>(34%)</i></div> | 0.5940594 | 0.405940594 | 0.5509066 | 0.44909344 | 0.6609986 | 0.339001447 |
Hospitalaria y <br>Domiciliaria | Todos los niveles | 3 | <div style='line-height:21px'>2<br><i>(67%)</i></div> | <div style='line-height:21px'>1<br><i>(33%)</i></div> | 396 | <div style='line-height:21px'>386<br><i>(97%)</i></div> | <div style='line-height:21px'>10<br><i>(3%)</i></div> | 111 | <div style='line-height:21px'>100<br><i>(90%)</i></div> | <div style='line-height:21px'>11<br><i>(10%)</i></div> | 0.6666667 | 0.333333333 | 0.9747475 | 0.02525253 | 0.9009009 | 0.099099099 |
Jóvenes y<br>Adultos | Primario | 178 | <div style='line-height:21px'>177<br><i>(99%)</i></div> | <div style='line-height:21px'>1<br><i>(1%)</i></div> | 4560 | <div style='line-height:21px'>4.543<br><i>(100%)</i></div> | <div style='line-height:21px'>17<br><i>(0%)</i></div> | 466 | <div style='line-height:21px'>464<br><i>(100%)</i></div> | <div style='line-height:21px'>2<br><i>(0%)</i></div> | 0.9943820 | 0.005617978 | 0.9962719 | 0.00372807 | 0.9957082 | 0.004291845 |
Jóvenes y<br>Adultos | Secundario | 136 | <div style='line-height:21px'>111<br><i>(82%)</i></div> | <div style='line-height:21px'>25<br><i>(18%)</i></div> | 38332 | <div style='line-height:21px'>33.425<br><i>(87%)</i></div> | <div style='line-height:21px'>4.907<br><i>(13%)</i></div> | 7385 | <div style='line-height:21px'>6.936<br><i>(94%)</i></div> | <div style='line-height:21px'>449<br><i>(6%)</i></div> | 0.8161765 | 0.183823529 | 0.8719869 | 0.12801315 | 0.9392011 | 0.060798917 |
Artística | 33 | <div style='line-height:21px'>28<br><i>(85%)</i></div> | <div style='line-height:21px'>5<br><i>(15%)</i></div> | 9700 | <div style='line-height:21px'>8.659<br><i>(89%)</i></div> | <div style='line-height:21px'>1.041<br><i>(11%)</i></div> | 594 | <div style='line-height:21px'>510<br><i>(86%)</i></div> | <div style='line-height:21px'>84<br><i>(14%)</i></div> | 0.8484848 | 0.151515152 | 0.8926804 | 0.10731959 | 0.8585859 | 0.141414141 | |
Formación<br>Profesional | 83 | <div style='line-height:21px'>83<br><i>(100%)</i></div> | 32623 | <div style='line-height:21px'>32.623<br><i>(100%)</i></div> | 641 | <div style='line-height:21px'>641<br><i>(100%)</i></div> | 1.0000000 | 0.000000000 | 1.0000000 | 0.00000000 | 1.0000000 | 0.000000000 |
Agregamos un tema predefinido a la tabla, en este caso el famoso FiveThirtyEight. Este tema servirá como base.
<- tabla1 |>
tabla2 gt_theme_538()
tabla2
Modalidad | Nivel | UE_Total | UE_Estatal | UE_Privado | ALUM_Total | ALUM_Estatal | ALUM_Privado | PD_Total | PD_Estatal | PD_Privado | percents_ue | percents_ue2 | percents_alu | percents_alu2 | percents_pd | percents_pd2 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Común | Inicial | 1757 | <div style='line-height:21px'>1.444<br><i>(82%)</i></div> | <div style='line-height:21px'>313<br><i>(18%)</i></div> | 132342 | <div style='line-height:21px'>96.631<br><i>(73%)</i></div> | <div style='line-height:21px'>35.711<br><i>(27%)</i></div> | 10512 | <div style='line-height:21px'>6.768<br><i>(64%)</i></div> | <div style='line-height:21px'>3.744<br><i>(36%)</i></div> | 0.8218554 | 0.178144565 | 0.7301612 | 0.26983875 | 0.6438356 | 0.356164384 |
Común | Primario | 2042 | <div style='line-height:21px'>1.724<br><i>(84%)</i></div> | <div style='line-height:21px'>318<br><i>(16%)</i></div> | 354360 | <div style='line-height:21px'>256.150<br><i>(72%)</i></div> | <div style='line-height:21px'>98.210<br><i>(28%)</i></div> | 31420 | <div style='line-height:21px'>23.544<br><i>(75%)</i></div> | <div style='line-height:21px'>7.876<br><i>(25%)</i></div> | 0.8442703 | 0.155729677 | 0.7228525 | 0.27714753 | 0.7493316 | 0.250668364 |
Común | Secundario | 932 | <div style='line-height:21px'>517<br><i>(55%)</i></div> | <div style='line-height:21px'>415<br><i>(45%)</i></div> | 346705 | <div style='line-height:21px'>208.603<br><i>(60%)</i></div> | <div style='line-height:21px'>138.102<br><i>(40%)</i></div> | 60133 | <div style='line-height:21px'>40.415<br><i>(67%)</i></div> | <div style='line-height:21px'>19.718<br><i>(33%)</i></div> | 0.5547210 | 0.445278970 | 0.6016729 | 0.39832711 | 0.6720935 | 0.327906474 |
Común | Superior | 207 | <div style='line-height:21px'>83<br><i>(40%)</i></div> | <div style='line-height:21px'>124<br><i>(60%)</i></div> | 76736 | <div style='line-height:21px'>45.014<br><i>(59%)</i></div> | <div style='line-height:21px'>31.722<br><i>(41%)</i></div> | 10159 | <div style='line-height:21px'>5.525<br><i>(54%)</i></div> | <div style='line-height:21px'>4.634<br><i>(46%)</i></div> | 0.4009662 | 0.599033816 | 0.5866086 | 0.41339137 | 0.5438527 | 0.456147259 |
Especial | Todos los niveles | 101 | <div style='line-height:21px'>60<br><i>(59%)</i></div> | <div style='line-height:21px'>41<br><i>(41%)</i></div> | 5019 | <div style='line-height:21px'>2.765<br><i>(55%)</i></div> | <div style='line-height:21px'>2.254<br><i>(45%)</i></div> | 2764 | <div style='line-height:21px'>1.827<br><i>(66%)</i></div> | <div style='line-height:21px'>937<br><i>(34%)</i></div> | 0.5940594 | 0.405940594 | 0.5509066 | 0.44909344 | 0.6609986 | 0.339001447 |
Hospitalaria y <br>Domiciliaria | Todos los niveles | 3 | <div style='line-height:21px'>2<br><i>(67%)</i></div> | <div style='line-height:21px'>1<br><i>(33%)</i></div> | 396 | <div style='line-height:21px'>386<br><i>(97%)</i></div> | <div style='line-height:21px'>10<br><i>(3%)</i></div> | 111 | <div style='line-height:21px'>100<br><i>(90%)</i></div> | <div style='line-height:21px'>11<br><i>(10%)</i></div> | 0.6666667 | 0.333333333 | 0.9747475 | 0.02525253 | 0.9009009 | 0.099099099 |
Jóvenes y<br>Adultos | Primario | 178 | <div style='line-height:21px'>177<br><i>(99%)</i></div> | <div style='line-height:21px'>1<br><i>(1%)</i></div> | 4560 | <div style='line-height:21px'>4.543<br><i>(100%)</i></div> | <div style='line-height:21px'>17<br><i>(0%)</i></div> | 466 | <div style='line-height:21px'>464<br><i>(100%)</i></div> | <div style='line-height:21px'>2<br><i>(0%)</i></div> | 0.9943820 | 0.005617978 | 0.9962719 | 0.00372807 | 0.9957082 | 0.004291845 |
Jóvenes y<br>Adultos | Secundario | 136 | <div style='line-height:21px'>111<br><i>(82%)</i></div> | <div style='line-height:21px'>25<br><i>(18%)</i></div> | 38332 | <div style='line-height:21px'>33.425<br><i>(87%)</i></div> | <div style='line-height:21px'>4.907<br><i>(13%)</i></div> | 7385 | <div style='line-height:21px'>6.936<br><i>(94%)</i></div> | <div style='line-height:21px'>449<br><i>(6%)</i></div> | 0.8161765 | 0.183823529 | 0.8719869 | 0.12801315 | 0.9392011 | 0.060798917 |
Artística | 33 | <div style='line-height:21px'>28<br><i>(85%)</i></div> | <div style='line-height:21px'>5<br><i>(15%)</i></div> | 9700 | <div style='line-height:21px'>8.659<br><i>(89%)</i></div> | <div style='line-height:21px'>1.041<br><i>(11%)</i></div> | 594 | <div style='line-height:21px'>510<br><i>(86%)</i></div> | <div style='line-height:21px'>84<br><i>(14%)</i></div> | 0.8484848 | 0.151515152 | 0.8926804 | 0.10731959 | 0.8585859 | 0.141414141 | |
Formación<br>Profesional | 83 | <div style='line-height:21px'>83<br><i>(100%)</i></div> | 32623 | <div style='line-height:21px'>32.623<br><i>(100%)</i></div> | 641 | <div style='line-height:21px'>641<br><i>(100%)</i></div> | 1.0000000 | 0.000000000 | 1.0000000 | 0.00000000 | 1.0000000 | 0.000000000 |
Ahora agregaremos las columnas que tienen la barra porcentual indicando la distribución de totales por tipo de gestión (estatal o privada). Cabe destacar que utilizaremos un esquema de colores que permita diferenciar cada dimensión: Unidades Educativas, Alumnos y Personal Docente.
<- tabla2 |>
tabla3 # Creamos barras de porcentaje
gt_plt_bar_pct(column = percents_ue, fill = "#5e2a72", background = "#B0AEB0") |>
gt_plt_bar_pct(column = percents_alu, fill = "#d5676d", background = "#B0AEB0") |>
gt_plt_bar_pct(column = percents_pd, fill = "#4f91b4", background = "#B0AEB0") |>
# Ocultamos algunas columnas
cols_hide(
columns = c(percents_ue2, percents_alu2, percents_pd2)
)
tabla3