Capítulo19 Datos Ordenados
## [1] "2026-09-09"
El tema proviene de los siguientes sitios.
English: https://r4ds.had.co.nz/tidy-data.html
Español: https://es.r4ds.hadley.nz/12-tidy.html
19.1 Temas: Datos Ordenados
- Las tres reglas de los datos ordenados
- Por qué conviene ordenarlos, aunque cueste trabajo
pivot_longer(): de ancho a largopivot_wider(): de largo a anchoseparate()yunite(): partir y juntar columnas- Valores faltantes implícitos y explícitos
19.3 Las tres reglas
Datos ordenados (tidy data): cada variable es una columna, cada observación es una fila y cada valor ocupa su propia celda. Con este formato el tidyverse trabaja de forma más natural.
Las tres reglas están relacionadas: si cumples dos, la tercera sale sola. En la práctica se reducen a dos instrucciones:
- Pon cada conjunto de datos en su propia tabla.
- Pon cada variable en su propia columna.
Lo difícil no es la definición, es reconocer cuál es la variable en un conjunto concreto. Y eso depende de la pregunta: en una tabla de mediciones repetidas, ¿la variable es “el peso” o son “el peso en enero” y “el peso en julio”? Casi siempre la respuesta correcta es la primera, y la fecha es otra variable.
El concepto de tidy data (datos ordenados) fue formalizado por Hadley Wickham en un influyente artículo de 2014. La idea (una variable por columna, una observación por fila) unificó la forma de preparar datos para el análisis.
19.3.1 ¿Por qué molestarse?
Ordenar una tabla da trabajo y no produce ningún resultado nuevo, así que la pregunta es legítima. Hay dos razones.
La primera es consistencia: si todos los conjuntos tienen la misma forma, las herramientas que aprendiste sirven para todos. No hay que reaprender nada al cambiar de proyecto.
La segunda es que R trabaja por columnas. mutate() opera sobre una columna
entera, group_by() agrupa por los valores de una columna, ggplot() mapea una
columna a un eje. Cuando la variable que te interesa está repartida entre cinco
columnas, ninguna de esas herramientas sirve: no puedes agrupar por “el año” si
el año es el nombre de la columna en vez de un valor.
19.4 Las cinco tablas del ejemplo
Los cinco conjuntos siguientes contienen exactamente la misma información: casos de tuberculosis y población de tres países en 1999 y en 2000. Lo único que cambia es la forma. Míralos con calma antes de seguir: solo uno de ellos está ordenado.
## # A tibble: 6 × 4
## pais anio casos poblacion
## <chr> <dbl> <dbl> <dbl>
## 1 Afganistán 1999 745 19987071
## 2 Afganistán 2000 2666 20595360
## 3 Brasil 1999 37737 172006362
## 4 Brasil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
## # A tibble: 12 × 4
## pais anio tipo cuenta
## <chr> <dbl> <chr> <dbl>
## 1 Afganistán 1999 casos 745
## 2 Afganistán 1999 población 19987071
## 3 Afganistán 2000 casos 2666
## 4 Afganistán 2000 población 20595360
## 5 Brasil 1999 casos 37737
## 6 Brasil 1999 población 172006362
## 7 Brasil 2000 casos 80488
## 8 Brasil 2000 población 174504898
## 9 China 1999 casos 212258
## 10 China 1999 población 1272915272
## 11 China 2000 casos 213766
## 12 China 2000 población 1280428583
## # A tibble: 6 × 3
## pais anio tasa
## <chr> <dbl> <chr>
## 1 Afganistán 1999 745/19987071
## 2 Afganistán 2000 2666/20595360
## 3 Brasil 1999 37737/172006362
## 4 Brasil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
## # A tibble: 3 × 3
## pais `1999` `2000`
## <chr> <dbl> <dbl>
## 1 Afganistán 745 2666
## 2 Brasil 37737 80488
## 3 China 212258 213766
## # A tibble: 3 × 3
## pais `1999` `2000`
## <chr> <dbl> <dbl>
## 1 Afganistán 19987071 20595360
## 2 Brasil 172006362 174504898
## 3 China 1272915272 1280428583
La respuesta es tabla1: tiene cuatro columnas (pais, anio, casos,
poblacion) y cada una es una variable. Las otras cuatro están mal, cada una a
su manera:
tabla2mete dos variables distintas (casosypoblación) en una sola columna de valores, y usa otra columna para decir cuál es cuál. Cada observación quedó partida en dos filas.tabla3guarda dos valores en la misma celda:745/19987071es texto, no un número, y no se puede dividir ni graficar.tabla4aytabla4busan los años como nombres de columna. El año es una variable y está escondido en la cabecera. Además hacen falta dos tablas para lo que debería ser una.
Una señal casi infalible de que una tabla no está ordenada: los nombres de las
columnas son valores (1999, 2000, enero, febrero, control,
tratamiento) en vez de nombres de variables.
Con tabla1, calcular la tasa de casos por cada diez mil habitantes es una línea:
## # A tibble: 6 × 5
## pais anio casos poblacion tasa
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Afganistán 1999 745 19987071 0.373
## 2 Afganistán 2000 2666 20595360 1.29
## 3 Brasil 1999 37737 172006362 2.19
## 4 Brasil 2000 80488 174504898 4.61
## 5 China 1999 212258 1272915272 1.67
## 6 China 2000 213766 1280428583 1.67
Con cualquiera de las otras cuatro, hay que ordenarlas primero. De eso trata el resto del capítulo.
19.5 El paquete tidyr
Las funciones pivot_longer() y pivot_wider() de tidyr son las herramientas principales para pasar los datos entre el formato ancho y el formato largo.
pivot_longer() y pivot_wider() (tidyr): cambiar la forma de la tabla.
pivot_longer(): pasa de ancho a largo (junta varias columnas en pares nombre-valor).pivot_wider(): pasa de largo a ancho (reparte una columna en varias).- Uso: dejar los datos ordenados para poder graficar y resumir con facilidad.
Las dos son opuestas: lo que hace una, la otra lo deshace. Casi siempre se usa
pivot_longer(), porque el problema más común con diferencia es el de los
nombres de columna que en realidad son valores.
19.5.1 pivot_longer(): de ancho a largo
tabla4a tiene los años como nombres de columna. Para arreglarla hay que
contestar tres preguntas:
- ¿Cuáles columnas hay que mover? Aquí,
1999y2000. Van entre acentos graves porque un nombre que empieza por número no es un nombre válido en R. - ¿Cómo se llama la variable escondida en los nombres? Se llama
anio, y eso va ennames_to. - ¿Cómo se llama la variable escondida en los valores? Se llama
casos, y eso va envalues_to.
## # A tibble: 6 × 3
## pais anio casos
## <chr> <chr> <dbl>
## 1 Afganistán 1999 745
## 2 Afganistán 2000 2666
## 3 Brasil 1999 37737
## 4 Brasil 2000 80488
## 5 China 1999 212258
## 6 China 2000 213766
La tabla pasó de 3 filas y 3 columnas a 6 filas y 3 columnas. Es más larga y más estrecha, y de ahí el nombre de la función.
El anio que sale de pivot_longer() es texto, no un número, porque venía
de un nombre de columna y los nombres son texto. Si vas a ordenar por año o
restar años, conviértelo: mutate(anio = as.integer(anio)), o usa
names_transform = list(anio = as.integer) dentro de la misma llamada.
Lo mismo con la tabla de población, y después se unen las dos por sus columnas comunes:
tabla4a_larga <- tabla4a |>
pivot_longer(c(`1999`, `2000`), names_to = "anio", values_to = "casos")
tabla4b_larga <- tabla4b |>
pivot_longer(c(`1999`, `2000`), names_to = "anio", values_to = "poblacion")
left_join(tabla4a_larga, tabla4b_larga)## # A tibble: 6 × 4
## pais anio casos poblacion
## <chr> <chr> <dbl> <dbl>
## 1 Afganistán 1999 745 19987071
## 2 Afganistán 2000 2666 20595360
## 3 Brasil 1999 37737 172006362
## 4 Brasil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
El resultado es tabla1. Ese left_join() es el tema del capítulo siguiente; por
ahora basta con ver que dos tablas ordenadas se combinan sin esfuerzo, y dos
tablas desordenadas no.
19.5.2 pivot_wider(): de largo a ancho
El problema de tabla2 es el contrario: una observación está repartida en varias
filas. Aquí las preguntas son dos:
- ¿Cuál columna tiene los nombres de las variables nuevas?
tipo, que va ennames_from. - ¿Cuál columna tiene los valores?
cuenta, que va envalues_from.
## # A tibble: 6 × 4
## pais anio casos población
## <chr> <dbl> <dbl> <dbl>
## 1 Afganistán 1999 745 19987071
## 2 Afganistán 2000 2666 20595360
## 3 Brasil 1999 37737 172006362
## 4 Brasil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
De 12 filas a 6. Fíjate en que la columna nueva se llama población, con acento,
porque ese era el valor que estaba dentro de la columna tipo: pivot_wider()
usa los valores tal como vienen para nombrar las columnas.
pivot_wider() se usa mucho menos que pivot_longer() para ordenar datos, pero
es la herramienta de siempre para presentar un resultado. Una tabla larga es
la que R quiere; una tabla ancha es la que un lector entiende de un vistazo.
19.6 separate() y unite()
Estas dos resuelven el problema de tabla3: dos valores metidos en la misma
celda.
separate() y unite() (tidyr): partir una columna en varias, y juntar varias en una.
separate(columna, into = c("a", "b"), sep = "/"): parte por el separador que le digas. Si no le dices ninguno, parte por el primer carácter que no sea alfanumérico.convert = TRUE: después de partir, adivina el tipo de las columnas nuevas. Sin esto, todo sale como texto.unite(nueva, a, b, sep = "_"): el camino contrario, junta varias columnas en una.
## # A tibble: 6 × 4
## pais anio casos poblacion
## <chr> <dbl> <chr> <chr>
## 1 Afganistán 1999 745 19987071
## 2 Afganistán 2000 2666 20595360
## 3 Brasil 1999 37737 172006362
## 4 Brasil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
Funciona, pero mira los tipos: casos y poblacion son texto. Con
convert = TRUE quedan numéricos y ya se puede calcular con ellos:
tabla3 |>
separate(tasa, into = c("casos", "poblacion"), sep = "/", convert = TRUE) |>
mutate(tasa = casos / poblacion * 10000)## # A tibble: 6 × 5
## pais anio casos poblacion tasa
## <chr> <dbl> <int> <int> <dbl>
## 1 Afganistán 1999 745 19987071 0.373
## 2 Afganistán 2000 2666 20595360 1.29
## 3 Brasil 1999 37737 172006362 2.19
## 4 Brasil 2000 80488 174504898 4.61
## 5 China 1999 212258 1272915272 1.67
## 6 China 2000 213766 1280428583 1.67
unite() hace el camino de vuelta:
tabla3 |>
separate(tasa, into = c("casos", "poblacion"), sep = "/") |>
unite(tasa_otra_vez, casos, poblacion, sep = "/")## # A tibble: 6 × 3
## pais anio tasa_otra_vez
## <chr> <dbl> <chr>
## 1 Afganistán 1999 745/19987071
## 2 Afganistán 2000 2666/20595360
## 3 Brasil 1999 37737/172006362
## 4 Brasil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
En las versiones recientes de tidyr estas dos funciones tienen sucesoras con
nombres más precisos: separate_wider_delim(), separate_wider_position() y
separate_longer_delim(). Hacen lo mismo con más control y mejores mensajes de
error. separate() y unite() siguen funcionando, y son las que usa el libro de
R4DS en el que se basa el curso.
Ver vignettes: https://tidyr.tidyverse.org/articles/pivot.html
19.7 Valores faltantes implícitos y explícitos
Un valor puede faltar de dos maneras, y la diferencia importa.
- Explícito: ahí está la fila, con un
NAen la celda. Se ve. - Implícito: la fila sencillamente no existe. No se ve, y por eso es más peligroso.
Cambiar la forma de una tabla convierte una clase en la otra. Al pasar a ancho,
las combinaciones que no existían aparecen como NA; al pasar a largo, esos NA
se pueden volver a quitar.
mediciones <- tibble(
parcela = c("P1", "P1", "P2"),
anio = c(2023, 2024, 2023),
plantas = c(12, 15, 30)
)
mediciones## # A tibble: 3 × 3
## parcela anio plantas
## <chr> <dbl> <dbl>
## 1 P1 2023 12
## 2 P1 2024 15
## 3 P2 2023 30
## # A tibble: 2 × 3
## parcela `2023` `2024`
## <chr> <dbl> <dbl>
## 1 P1 12 15
## 2 P2 30 NA
La parcela P2 no tenía fila para 2024: era un faltante implícito. Al ensanchar la tabla se hizo explícito, y ahora se ve.
complete(parcela, anio) hace explícitos todos los faltantes sin cambiar la
forma de la tabla, y es la manera de contestar la pregunta “¿me falta algún dato
que debería estar?”. Es de las primeras cosas que conviene correr con datos de
campo.
19.8 Ejercicios del libro R4DS
Hacer los ejercicios de las secciones 12.2.1, 12.3.3 y 12.4.3 del libro en español.
19.9 Ejercicios del capítulo
Sobre los ejercicios de este capítulo. Cada ejercicio se entrega con tres
cosas: el script, el resultado (que el bloque corra) y una explicación
en palabras. Los ejercicios usan paises y millas del paquete datos, y
tablas que escribirás a mano, no las tabla1 a tabla4b del capítulo. La hoja
completa para entregar está en
Ejercicios/Ejercicios_Capitulo_19_datos-ordenados.Rmd.
19.9.1 Ejercicio 1. ¿Está ordenada?
Mira paises con glimpse(). Contesta, columna por columna, si cada una es una
variable, y decide si la tabla está ordenada.
Verificación: paises tiene 1704 filas y 6 columnas.
En palabras: justifica tu respuesta con las tres reglas. ¿Cuál es la observación en esta tabla: un país, o un país en un año?
19.9.2 Ejercicio 2. De largo a ancho
Con paises, quédate solo con pais, anio y esperanza_de_vida, y ensancha
la tabla con pivot_wider() para que cada año sea una columna.
Verificación: la tabla ancha debe tener 142 filas y 13 columnas (el país más los doce años).
En palabras: esta tabla ancha, ¿está ordenada? ¿Para qué sirve mejor que la original, y para qué sirve peor?
19.9.3 Ejercicio 3. Y de vuelta
Toma la tabla ancha del ejercicio anterior y devuélvela a la forma larga con
pivot_longer(). Ocúpate de que anio vuelva a ser numérico.
Verificación: la tabla debe volver a tener 1704 filas, y anio debe ser
numérico, no texto.
En palabras: si no conviertes anio, ¿qué pasa al ordenar con arrange()?
Pruébalo y explica el resultado.
19.9.4 Ejercicio 4. Dos columnas que son una variable
En millas, ciudad y autopista son dos columnas, pero miden lo mismo en
dos condiciones distintas. Pásalas a formato largo con names_to = "tipo_de_via"
y values_to = "millas_por_galon".
Verificación: la tabla larga debe tener 468 filas y 11 columnas.
En palabras: con la tabla larga, haz un diagrama de caja del consumo por
tipo_de_via. ¿Podrías haber hecho esa gráfica con la tabla original? Explica
por qué no de una sola vez.
19.9.5 Ejercicio 5. Juntar y volver a partir
Con paises, usa unite() para crear una columna pais_anio que junte pais y
anio con un guion bajo. Después usa separate() para deshacerlo.
Verificación: después de separate() sin convert = TRUE, anio es
texto; con convert = TRUE, vuelve a ser numérico.
En palabras: ¿por qué separate() no puede adivinar el tipo por su cuenta?
¿Y qué pasaría si algún país tuviera un guion bajo en el nombre?
19.9.6 Ejercicio 6. El faltante que no se ve
Escribe a mano una tabla de cuatro parcelas medidas en tres años, pero quita
tres combinaciones a propósito. Ensánchala con pivot_wider() y después usa
complete() sobre la tabla original.
Verificación: la tabla ancha debe enseñar exactamente tres NA, y
complete() debe llevar la tabla larga a 12 filas.
En palabras: las dos maneras enseñan los mismos tres huecos. ¿Cuál usarías en un análisis de datos de campo y por qué? ¿Qué habría pasado si nunca los hubieras hecho explícitos y hubieras calculado un promedio por parcela?
19.9.7 Ejercicio 7 (BONO). Desordenar a propósito
Convierte millas en una tabla del estilo de tabla4a: una fila por clase,
una columna por anio, y en las celdas el promedio de autopista.
Verificación: 7 filas y 3 columnas, y los nombres de dos de las columnas son años.
En palabras: acabas de producir una tabla desordenada a propósito, y sin embargo es la que pondrías en un informe. Explica esa contradicción: ¿cuándo conviene una tabla ordenada y cuándo una ancha?