-
Notifications
You must be signed in to change notification settings - Fork 2
/
08-tablas.Rmd
259 lines (201 loc) · 9.86 KB
/
08-tablas.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# Tablas
Por defecto, la forma en que R Markdown muestra tablas es bastante feo porque muestra lo que verías si corrieras el código en la consola.
```{r, include = FALSE}
library(dplyr)
library(tidyr)
library(lubridate)
parques_ancho <- readr::read_csv("datos/parques_ancho.csv")
parques_largo <- parques_ancho %>%
pivot_longer(cols = -c("indice_tiempo", "residentes", "no_residentes", "total"),
names_to = "region_visitante",
values_to = "valor") %>%
mutate(region_visitante = stringr::str_replace(region_visitante, "buenos_aires*", "buenos-aires"),
region_visitante = stringr::str_replace(region_visitante, "no_residentes", "noresidentes")) %>%
separate(region_visitante, into = c("region", "tipo_visitante"), sep = "_") %>%
select(-c("residentes", "no_residentes", "total"))
parques_resumen <- parques_largo %>%
mutate(indice_tiempo = ym(indice_tiempo)) %>%
group_by(anio = year(indice_tiempo), region, tipo_visitante) %>%
summarise(valor = mean(valor)) %>%
filter(region %in% c("cordoba", "cuyo", "patagonia"),
anio >= 2020) %>%
pivot_wider(names_from = "tipo_visitante", values_from = "valor")
```
```{r, eval = FALSE}
library(dplyr)
library(tidyr)
library(lubridate)
parques_ancho <- readr::read_csv("http://datos.yvera.gob.ar/dataset/458bcbe1-855c-4bc3-a1c9-cd4e84fedbbc/resource/78aea6ed-761c-4659-bdf2-7fcb0f616fad/download/serie-tiempo-parques-nacionales-mensual.csv")
parques_largo <- parques_ancho %>%
pivot_longer(cols = -c("indice_tiempo", "residentes", "no_residentes", "total"),
names_to = "region_visitante",
values_to = "valor") %>%
mutate(region_visitante = stringr::str_replace(region_visitante, "buenos_aires*", "buenos-aires"),
region_visitante = stringr::str_replace(region_visitante, "no_residentes", "noresidentes")) %>%
separate(region_visitante, into = c("region", "tipo_visitante"), sep = "_") %>%
select(-c("residentes", "no_residentes", "total"))
parques_resumen <- parques_largo %>%
mutate(indice_tiempo = ym(indice_tiempo)) %>%
group_by(anio = year(indice_tiempo), region, tipo_visitante) %>%
summarise(valor = mean(valor)) %>%
filter(region %in% c("cordoba", "cuyo", "patagonia"),
anio >= 2020) %>%
pivot_wider(names_from = "tipo_visitante", values_from = "valor")
```
```{r}
parques_resumen
```
## Tablas simples con `kable`
Existen varios paquetes para mostrar tablas lindas pero una forma simple y sin vueltas es usando la función `kable()` del paquete **knitr**.
Sólo usando esta función ya devuelve una tabla con un diseño más limpio y acabado:
```{r}
library(knitr)
kable(parques_resumen)
```
La mayoría de las veces, el nombre de las columnas que queremos mostrar no va a ser igual que el nombre de las columnas en R.
En la tabla `parques_resumen`, los nombres están en minúscula, sin espacios y sin "caracteres especiales" como "ñ".
Esto es útil para comunicarse con R, pero no está bueno para comunicarse con otras personas.
El argumento `col.names` permite especificar el nombre de las columnas para mostrar:
```{r}
kable(parques_resumen,
col.names = c("Año", "Región", "No Residentes", "Residentes", "Total"))
```
En Español, en general usamos la coma para separar los decimales y el punto como separador de miles.
Además, esta tabla tiene el problema de la precisión innecesaria: ¿realmente tiene sentido reportar el promedio de visitantes con 5 decimales?
Para eso, hay que modificar el argumento `format.args` de esta manera:
```{r}
kable(parques_resumen,
col.names = c("Año", "Región", "No Residentes", "Residentes", "Total"),
format.args = list(decimal.mark = ",", big.mark = ".", digits = 1, scientific = FALSE))
```
En esta llamada hay varios elementos que son parte del argumento `format.args`:
- `decimal.mark = ","`: usar la coma para la marca de decimales,
- `big.mark = "."`: usar el punto para separador de miles,
- `digits = 1`: redondear todo a 1 cifra significativa,
- `scientific = FALSE`: no usar notación científica.
Uff... pero ponerle el punto de miles a los años queda raro.
La solución es convertir la columna `anio` en caracter.
De esta manera, no se ve afectada por el formato numérico.
```{r}
parques_resumen %>%
mutate(anio = as.character(anio)) %>%
kable(col.names = c("Año", "Región", "No Residentes", "Residentes", "Total"),
format.args = list(decimal.mark = ",", big.mark = ".", digits = 1, scientific = FALSE))
```
Un detalle final podría ser convertir en mayúsculas los nombres de las regiones.
Para eso se puede usar la función `str_to_sentence()` del paquete **stringr**.
```{r}
parques_resumen %>%
mutate(anio = as.character(anio),
region = stringr::str_to_sentence(region)) %>%
kable(col.names = c("Año", "Región", "No Residentes", "Residentes", "Total"),
format.args = list(decimal.mark = ",", big.mark = ".", digits = 1, scientific = FALSE))
```
`kable` es una función diseñada para ser simple y hacer pocas cosas, para hacer cosas un poco mas complicadas está el paquete **kableExtra**.
## Supertablas con kableExtra
El paquete kableExtra, como su nombre lo indica, nació para extender el poder de la función `kable()`.
```{r message=FALSE}
library(kableExtra) # instalar con install.packages("kableExtra")
```
Primero, guardamos la tabla anterior para editarla con las operaciones de kableExtra.
```{r}
parques_tabla <- parques_resumen %>%
mutate(anio = as.character(anio),
region = stringr::str_to_sentence(region)) %>%
kable(col.names = c("Año", "Región", "No Residentes", "Residentes", "Total"),
format.args = list(decimal.mark = ",", big.mark = ".", digits = 1, scientific = FALSE))
```
La primera columna de la tabla de arriba es un tanto redundante.
Sería mejor agrupar las filas según el año.
Esto se consigue con la función `collapse_rows()`:
```{r}
parques_tabla %>%
collapse_rows(columns = 1, valign = "top") %>%
kable_styling()
```
El primer argumento es el número de la columna que queremos agrupar.
En este caso, la columna `anio` es la primera.
El segundo argumento es la alineación vertical.
Por defecto, `collapse_rows()` pone las etiquetas en el centro, pero la convención más general es ponerlas arriba.
¿Qué es esa `kable_styling()`?
kableExtra permite cambiar el estilo de las tablas muy fácilmente.
`kable_styling()` es el estilo por defecto, que es igual al que produce `kable()`, pero existen muchos otros.
Si viste tablas hechas en LaTeX, quizás este estilo te resulte familiar:
```{r}
parques_tabla %>%
collapse_rows(columns = 1, valign = "top") %>%
kable_classic_2()
```
La función `column_spec()` permite cambiar los parámetros gráficos de una o más columnas.
En este caso cambiamos la segunda columna (`column = 2`) para que las palabras aparezcan italizadas (`italic = TRUE`):
```{r}
parques_tabla %>%
column_spec(column = 2, italic = TRUE) %>%
collapse_rows(columns = 1, valign = "top") %>%
kable_styling()
```
Lo notable de `column_spec()` es que en sus argumentos se pueden poner vectores de manera de generar formato condicional.
Para resaltar con negrita el año 2021:
```{r}
parques_tabla %>%
column_spec(column = 1, bold = (parques_resumen$anio == 2021)) %>%
collapse_rows(columns = 1, valign = "top") %>%
kable_styling()
```
Conviene detenerse para mirar un poco con detalle el código.
La llamada a `column_spec()` está cambiando el formato de la columna 1.
En particular, va a determinar si el texto está en negrita (bold) o no.
Y la forma para determinarlo es el vector `parques_resumen$anio == 2021`.
¿Qué es ese vector?
```{r}
parques_resumen$anio == 2021
```
Por lo tanto, `column_spec(column = 1, bold = (parques_resumen$anio == 2021))` va a hacer que las tres últimas filas de la columna uno estén en negrita, y las demás no.
Luego, `collapse_rows()` colapsa las filas según el año y entonces esas tres últimas filas se transforman en una.
En este caso el órden de las operaciones es importante.
Si primero colapsamos y luego damos formato, el resultado no es el esperado:
```{r}
parques_tabla %>%
collapse_rows(columns = 1, valign = "top") %>%
column_spec(column = 1, bold = (parques_resumen$anio == 2021)) %>%
kable_styling()
```
Esto da un montón de flexibilidad en el estilo del texto.
Por ejemplo, se puede hacer que el color del texto cambie según el valor usando `column_spec()` y `spec_color()`.
```{r}
parques_tabla %>%
column_spec(5, color = spec_color(parques_resumen$total)) %>%
collapse_rows(columns = 1, valign = "top") %>%
kable_styling()
```
La función nueva, `spec_color()`, genera colores a partir de un vector.
Podés ver cómo funciona en esta linea:
```{r}
spec_color(parques_resumen$total)
```
Esos números son representaciones en hexadecimal de los colores que ves en la tabla.
```{r}
scales::show_col(spec_color(parques_resumen$total))
```
Así como se puede cambiar el estilo de las columnas con `column_spec()`, se puede cambiar el estilo de las filas con `row_spec()`.
Por ejemplo, se puede resaltar cada 2 líneas con este código:
```{r}
parques_tabla %>%
row_spec(row = seq(2, nrow(parques_resumen), by = 2), background = "aquamarine") %>%
collapse_rows(columns = 1, valign = "top") %>%
kable_styling()
```
`row_spec()` está cambiando el fondo (background) al color "aquamarine" (que es ese turquesa [●]{style="color:`r rgb(t(col2rgb("aquamarine"))/255)`"}) a las filas indicadas por `seq(2, nrow(paises_seleccion), by = 2)`.
¿Qué es eso?
`seq()` genera una secuencia (de **seq**uence) de números empezando en 2, terminando en la cantidad de filas de `parques_resumen` y saltando de a dos.
En resumen:
```{r}
seq(2, nrow(parques_resumen), by = 2)
```
Como caso especial, se puede usar `row = 0` en `row_spec()` para cambiar el formato del encabezado.
```{r}
parques_tabla %>%
row_spec(row = 0, underline = TRUE) %>%
collapse_rows(columns = 1, valign = "top") %>%
kable_styling()
```