third(second(first(datos)))
Tidydata
Cuadernos prácticos de Software II del Grado en Ciencia de Datos Aplicada (curso 2024-2025)
1 Tidydata
1.1 R base vs tidyverse
Hasta ahora todo lo que hemos hecho en R
lo hemos realizado en el paradigma de programación conocido como R base. Y es que cuando R
nació como lenguaje, muchos de los que programaban en él imitaron formas y metodologías heredadas de otros lenguajes, basado en el uso de
Bucles for
Bucles while
Estructuras if-else
Y aunque conocer dichas estructuras puede sernos en algunos casos interesantes, en la mayoría de ocasiones han quedado caducas y vamos a poder evitarlas (en especial los bucles) ya que R
está especialmente diseñado para trabajar de manera funcional (en lugar de elemento a elemento).
Profundizaremos en las diferencias más adelante cuando tengamos algo más de conocimiento.
1.2 ¿Qué es tidyverse?
En ese contexto de programación funcional, hace una década nacía {tidyverse}
, un «universo» de paquetes para garantizar un flujo de trabajo eficiente, coherente y lexicográficamente sencillo de entender, basado en la idea de que nuestros datos están limpios y ordenados (tidy)
{tibble}
: optimizando data.frame{tidyr}
: limpieza de datos{readr}
: carga datos rectangulares (.csv),{readxl}
para importar archivos .xls y .xlsx{dplyr}
: gramática para depurar{stringr}
: manejo de textos{purrr}
: manejo de listas{forcats}
: manejo de cualitativas{ggplot2}
: visualización de datos{lubridate}
manejo de fechas{rvest}
: web scraping{tidymodels}
: modelización/predicción
Todos estos paquetes descansan sobre una idea: hay muchas formas de trabajar de manera sucia y desordenada pero solo una de trabajar de manera estandarizada.
Tidy datasets are all alike, but every messy dataset is messy in its own way (Hadley Wickham, Chief Scientist en RStudio)
TIDYVERSE
El universo de paquetes {tidyverse}
se basa en la idea introducida por Hadley Wickham (el Dios al que rezamos) de estandarizar el formato de los datos para
- sistematizar la depuración
- hacer más sencillo su manipulación.
- código legible
1.3 Mandamientos del tidy data
Lo primero por tanto será entender qué son los conjuntos tidydata ya que todo {tidyverse}
se basa en que los datos están estandarizados.
Cada variable en una única columna
Cada individuo en una fila diferente
Cada celda con un único valor
Cada dataset en un tibble
Si queremos cruzar múltiples tablas debemos tener una columna común
En {tidyverse}
será clave el operador pipe (tubería) definido como |>
(ctrl+shift+M): será una tubería que recorre los datos y los transforma.
¿Para qué sirve? En R base (hasta ahora) si queríamos aplicar tres funciones first()
, second()
y third()
en orden, sería (lo hemos visto un poco en el caso práctico de funciones si lo has hecho 0_0)
En {tidyverse}
podremos leer de izquierda a derecha y separar los datos de las acciones
|> first() |> second() |> third() datos
Desde la versión 4.1.0 de R
disponemos de |>
, un pipe nativo disponible fuera de tidyverse, sustituyendo al antiguo pipe %>%
que dependía del paquete {magrittr}
(bastante problemático).
La principal ventaja es que el código sea muy legible (casi literal) pudiendo hacer grandes operaciones con los datos con apenas código.
|>
datos limpio(...) |>
filtro(...) |>
selecciono(...) |>
ordeno(...) |>
modifico(...) |>
renombro(...) |>
agrupo(...) |>
cuento(...) |>
resumo(...) |>
pinto(...)
1.4 Datos SUCIOS: messy data
¿Pero qué aspecto tienen los datos no tidy? Vamos a cargar la tabla table4a
del paquete {tidyr}
(ya lo tenemos cargado del entorno tidyverse).
library(tidyr)
table4a
# A tibble: 3 × 3
country `1999` `2000`
<chr> <dbl> <dbl>
1 Afghanistan 745 2666
2 Brazil 37737 80488
3 China 212258 213766
¿Qué puede estar fallando?
1.4.1 Pivotar: pivot_longer()
table4a
# A tibble: 3 × 3
country `1999` `2000`
<chr> <dbl> <dbl>
1 Afghanistan 745 2666
2 Brazil 37737 80488
3 China 212258 213766
❎ Cada fila representa dos observaciones (1999 y 2000) → las columnas 1999
y 2000
en realidad deberían ser en sí valores de una variable y no nombres de columnas.
Incluiremos una nueva columna que nos guarde el año y otra que guarde el valor de la variable de interés en cada uno de esos años. Y lo haremos con la función pivot_longer()
: pivotaremos la tabla a formato long:
|>
table4a pivot_longer(cols = c("1999", "2000"), names_to = "year", values_to = "cases")
# A tibble: 6 × 3
country year cases
<chr> <chr> <dbl>
1 Afghanistan 1999 745
2 Afghanistan 2000 2666
3 Brazil 1999 37737
4 Brazil 2000 80488
5 China 1999 212258
6 China 2000 213766
cols
: nombre de las variables a pivotarnames_to
: nombre de la nueva variable a la quemandamos la cabecera de la tabla (los nombres).values_to
: nombre de la nueva variable a la que vamos a mandar los datos.
1.4.2 Pivotar: pivot_wider()
Veamos otro ejemplo con la tabla table2
table2
# A tibble: 12 × 4
country year type count
<chr> <dbl> <chr> <dbl>
1 Afghanistan 1999 cases 745
2 Afghanistan 1999 population 19987071
3 Afghanistan 2000 cases 2666
4 Afghanistan 2000 population 20595360
5 Brazil 1999 cases 37737
6 Brazil 1999 population 172006362
7 Brazil 2000 cases 80488
8 Brazil 2000 population 174504898
9 China 1999 cases 212258
10 China 1999 population 1272915272
11 China 2000 cases 213766
12 China 2000 population 1280428583
¿Qué puede estar fallando?
❎ Cada observación está dividido en dos filas → los registros con el mismo año deberían ser el mismo
Lo que haremos será lo opuesto: con pivot_wider()
ensancharemos la tabla
|> pivot_wider(names_from = type, values_from = count) table2
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583
1.4.3 Separar: separate()
Veamos otro ejemplo con la tabla table3
table3
# A tibble: 6 × 3
country year rate
<chr> <dbl> <chr>
1 Afghanistan 1999 745/19987071
2 Afghanistan 2000 2666/20595360
3 Brazil 1999 37737/172006362
4 Brazil 2000 80488/174504898
5 China 1999 212258/1272915272
6 China 2000 213766/1280428583
¿Qué puede estar fallando?
❎ Cada celda contiene varios valores
Lo que haremos será hacer uso de la función separate()
para mandar separar cada valor a una columna diferente.
|> separate(rate, into = c("cases", "pop")) table3
# A tibble: 6 × 4
country year cases pop
<chr> <dbl> <chr> <chr>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583
Fíjate que los datos, aunque los ha separado, los ha mantenido como texto cuando en realidad deberían ser variables numéricas. Para ello podemos añadir el argumento opcional convert = TRUE
|> separate(rate, into = c("cases", "pop"), convert = TRUE) table3
# A tibble: 6 × 4
country year cases pop
<chr> <dbl> <int> <int>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583
1.4.4 Unir: unite()
Veamos el último ejemplo con la tabla table5
table5
# A tibble: 6 × 4
country century year rate
<chr> <chr> <chr> <chr>
1 Afghanistan 19 99 745/19987071
2 Afghanistan 20 00 2666/20595360
3 Brazil 19 99 37737/172006362
4 Brazil 20 00 80488/174504898
5 China 19 99 212258/1272915272
6 China 20 00 213766/1280428583
¿Qué puede estar fallando?
❎ Tenemos mismos valores divididos en dos columnas
Usaremos unite()
para unir los valores de siglo y año en una misma columna
|> unite(col = year_completo, century, year, sep = "") table5
# A tibble: 6 × 3
country year_completo rate
<chr> <chr> <chr>
1 Afghanistan 1999 745/19987071
2 Afghanistan 2000 2666/20595360
3 Brazil 1999 37737/172006362
4 Brazil 2000 80488/174504898
5 China 1999 212258/1272915272
6 China 2000 213766/1280428583
1.5 Ejemplo real: relig_income
Vamos a realizar un ejemplo juntos con la tabla relig_income
del paquete {tidyr}
. Como se indica en la ayuda ? relig_income
, la tabla representa la cantidad de personas que hay en cada tramo de ingresos anuales (20k = 20 000$) y en cada religión.
relig_income
# A tibble: 18 × 11
religion `<$10k` `$10-20k` `$20-30k` `$30-40k` `$40-50k` `$50-75k` `$75-100k`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Agnostic 27 34 60 81 76 137 122
2 Atheist 12 27 37 52 35 70 73
3 Buddhist 27 21 30 34 33 58 62
4 Catholic 418 617 732 670 638 1116 949
5 Don’t k… 15 14 15 11 10 35 21
6 Evangel… 575 869 1064 982 881 1486 949
7 Hindu 1 9 7 9 11 34 47
8 Histori… 228 244 236 238 197 223 131
9 Jehovah… 20 27 24 24 21 30 15
10 Jewish 19 19 25 25 30 95 69
11 Mainlin… 289 495 619 655 651 1107 939
12 Mormon 29 40 48 51 56 112 85
13 Muslim 6 7 9 10 9 23 16
14 Orthodox 13 17 23 32 32 47 38
15 Other C… 9 7 11 13 13 14 18
16 Other F… 20 33 40 46 49 63 46
17 Other W… 5 2 3 4 2 7 3
18 Unaffil… 217 299 374 365 341 528 407
# ℹ 3 more variables: `$100-150k` <dbl>, `>150k` <dbl>,
# `Don't know/refused` <dbl>
¿Es tidydata?
No lo es ya que en realidad solo deberíamos tener una variable de ingresos y la tenemos dividida en 11: todas ellas es la misma variable solo que adopta un valor diferente. ¿Cómo convertirla a tidy data?. La idea es pivotar todas las columnas de ingresos para que acaben en una sola columna llamada income
, y los valores (el número de personas) en otra llamada people
(por ejemplo). La tabla la haremos más larga y menos ancha así que…
<-
relig_tidy |>
relig_income pivot_longer(cols = "<$10k":"Don't know/refused", names_to = "income",
values_to = "people")
relig_tidy
# A tibble: 180 × 3
religion income people
<chr> <chr> <dbl>
1 Agnostic <$10k 27
2 Agnostic $10-20k 34
3 Agnostic $20-30k 60
4 Agnostic $30-40k 81
5 Agnostic $40-50k 76
6 Agnostic $50-75k 137
7 Agnostic $75-100k 122
8 Agnostic $100-150k 109
9 Agnostic >150k 84
10 Agnostic Don't know/refused 96
# ℹ 170 more rows
Vamos a hilar más fino: ahora mismo en la variable income
en realidad tenemos dos valores, el límite inferior y el superior de la renta. Vamos a separar dicha variable e ingresos en dos, llamadas income_inf
y income_sup
|>
relig_tidy # Separamos por -
separate(income, into = c("income_inf", "income_sup"), sep = "-")
Warning: Expected 2 pieces. Missing pieces filled with `NA` in 54 rows [1, 9, 10, 11,
19, 20, 21, 29, 30, 31, 39, 40, 41, 49, 50, 51, 59, 60, 61, 69, ...].
# A tibble: 180 × 4
religion income_inf income_sup people
<chr> <chr> <chr> <dbl>
1 Agnostic <$10k <NA> 27
2 Agnostic $10 20k 34
3 Agnostic $20 30k 60
4 Agnostic $30 40k 81
5 Agnostic $40 50k 76
6 Agnostic $50 75k 137
7 Agnostic $75 100k 122
8 Agnostic $100 150k 109
9 Agnostic >150k <NA> 84
10 Agnostic Don't know/refused <NA> 96
# ℹ 170 more rows
¿Está ya bien? Fíjate bien…
Si te fijas la primera columna el "$10k"
debería ser una cota superior, no inferior. ¿Cómo indicarle que separe bien ese caso? Le indicaremos que separe si encuentra "-"
o "<"
(usamos |
para separar ambas opciones)
<-
relig_tidy |>
relig_tidy # Separamos por -
separate(income, into = c("income_inf", "income_sup"), sep = "-|<")
Warning: Expected 2 pieces. Missing pieces filled with `NA` in 36 rows [9, 10, 19, 20,
29, 30, 39, 40, 49, 50, 59, 60, 69, 70, 79, 80, 89, 90, 99, 100, ...].
Piensa ahora como podemos convertir los límites de ingresos a numéricas (eliminando símbolos, letras, etc). Para ello usaremos el paquete {stringr}
que hemos visto antes, en concreto la función str_remove_all()
a la que le podemos pasar los caracteres que queremos eliminar (fíjate que $
al ser un caracter reservado en R
hay que indicárselo con \\$
)
library(stringr)
$income_inf <-
relig_tidystr_remove_all(relig_tidy$income_inf, "\\$|>|k")
$income_sup <-
relig_tidystr_remove_all(relig_tidy$income_sup, "\\$|>|k")
relig_tidy
# A tibble: 180 × 4
religion income_inf income_sup people
<chr> <chr> <chr> <dbl>
1 Agnostic "" 10 27
2 Agnostic "10" 20 34
3 Agnostic "20" 30 60
4 Agnostic "30" 40 81
5 Agnostic "40" 50 76
6 Agnostic "50" 75 137
7 Agnostic "75" 100 122
8 Agnostic "100" 150 109
9 Agnostic "150" <NA> 84
10 Agnostic "Don't now/refused" <NA> 96
# ℹ 170 more rows
Fíjate que a veces tenemos "Don't now/refused"
. ¿Qué deberíamos tener?
Debería ser un dato ausente así que usaremos if_else()
: si contiene dicha frase, NA
, en caso contrario su valor (consejo: str_detect()
para detectar patrones en textos, y evitar tener que escribir toda la palabra sin errores)
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
$income_inf <-
relig_tidyif_else(str_detect(relig_tidy$income_inf, "refused"), NA, relig_tidy$income_inf)
$income_sup <-
relig_tidyif_else(str_detect(relig_tidy$income_sup, "refused"), NA, relig_tidy$income_sup)
relig_tidy
# A tibble: 180 × 4
religion income_inf income_sup people
<chr> <chr> <chr> <dbl>
1 Agnostic "" 10 27
2 Agnostic "10" 20 34
3 Agnostic "20" 30 60
4 Agnostic "30" 40 81
5 Agnostic "40" 50 76
6 Agnostic "50" 75 137
7 Agnostic "75" 100 122
8 Agnostic "100" 150 109
9 Agnostic "150" <NA> 84
10 Agnostic <NA> <NA> 96
# ℹ 170 more rows
En la primera línea, ese ""
también debería ser `NA``
$income_inf <-
relig_tidyif_else(relig_tidy$income_inf == "", NA, relig_tidy$income_inf)
$income_suop <-
relig_tidyif_else(relig_tidy$income_sup == "", NA, relig_tidy$income_sup)
Además si te fijas los números son en realidad caracteres, así que vamos a convertirlos a números
$income_inf <- as.numeric(relig_tidy$income_inf)
relig_tidy$income_sup <- as.numeric(relig_tidy$income_sup)
relig_tidy relig_tidy
# A tibble: 180 × 5
religion income_inf income_sup people income_suop
<chr> <dbl> <dbl> <dbl> <chr>
1 Agnostic NA 10 27 10
2 Agnostic 10 20 34 20
3 Agnostic 20 30 60 30
4 Agnostic 30 40 81 40
5 Agnostic 40 50 76 50
6 Agnostic 50 75 137 75
7 Agnostic 75 100 122 100
8 Agnostic 100 150 109 150
9 Agnostic 150 NA 84 <NA>
10 Agnostic NA NA 96 <NA>
# ℹ 170 more rows
¿Se te ocurre alguna forma de «cuantificar numéricamente» los valores ausentes que tenemos en este caso? Si te fijas en realidad cuando hay ausente en el límite inferior en realidad podríamos poner un 0 (nadie puede ganar menos de eso) y cuando lo tenemos en el límite superior sería Inf
$income_inf <-
relig_tidyif_else(is.na(relig_tidy$income_inf), 0, relig_tidy$income_inf)
$income_sup <-
relig_tidyif_else(is.na(relig_tidy$income_sup), Inf, relig_tidy$income_sup)
relig_tidy
# A tibble: 180 × 5
religion income_inf income_sup people income_suop
<chr> <dbl> <dbl> <dbl> <chr>
1 Agnostic 0 10 27 10
2 Agnostic 10 20 34 20
3 Agnostic 20 30 60 30
4 Agnostic 30 40 81 40
5 Agnostic 40 50 76 50
6 Agnostic 50 75 137 75
7 Agnostic 75 100 122 100
8 Agnostic 100 150 109 150
9 Agnostic 150 Inf 84 <NA>
10 Agnostic 0 Inf 96 <NA>
# ℹ 170 more rows
Aunque nos haya llevado un rato este es el código completo resumido
<-
relig_tidy |>
relig_income pivot_longer(cols = "<$10k":"Don't know/refused", names_to = "income",
values_to = "people") |>
separate(income, into = c("income_inf", "income_sup"), sep = "-|<")
$income_inf <- str_remove_all(relig_tidy$income_inf, "\\$|>|k")
relig_tidy$income_sup <- str_remove_all(relig_tidy$income_sup, "\\$|>|k")
relig_tidy
$income_inf <-
relig_tidyif_else(str_detect(relig_tidy$income_inf, "refused") |
$income_inf == "", 0, as.numeric(relig_tidy$income_inf))
relig_tidy$income_sup <-
relig_tidyif_else(str_detect(relig_tidy$income_sup, "refused") |
$income_sup == "", Inf, as.numeric(relig_tidy$income_sup)) relig_tidy
¿Por qué era importante tenerlo en tidydata? Lo veremos más adelante al visualizar los datos pero esto ya nos permite realizar filtros muy rápidos con muy poco código.
Por ejemplo: ¿cuántas personas agnósticas con ingresos superiores (o iguales) a 30 tenemos?
# una línea de código
sum(relig_tidy$people[relig_tidy$religion == "Agnostic" & relig_tidy$income_inf >= 30])
[1] 609
1.6 💻 Tu turno
Intenta realizar los siguientes ejercicios sin mirar las soluciones
📝 Usa el dataset original relig_income
y trata de responder a la última pregunta: ¿cuántas personas agnósticas con ingresos superiores (o iguales) a 30 tenemos? Compara el código a realizar cuando tenemos tidydata a cuando no. ¿Cuál es más legible si no supieses R
? ¿Cuál tiene mayor probabilidad de error?
Code
sum(relig_income[relig_income$religion == "Agnostic",
c("$30-40k", "$40-50k", "$50-75k", "$75-100k", "$100-150k", ">150k")])
📝 Usando relig_tidy
determina quién tiene más ingresos medios, ¿católicos (Catholic
) o agnósticos (Agnostic
)? Crea antes una variable avg_income
(ingresos medios por intervalo): si hay 5 personas entre 20 y 30, y 3 personas entre 30 y 50, la media sería \((25*5 + 40*3)/8\) (si es Inf
por arriba, NA
)
Code
$avg_income <-
relig_tidyif_else(is.infinite(relig_tidy$income_sup), NA, (relig_tidy$income_sup + relig_tidy$income_inf)/2)
# Agnosticos vs catolicos
sum((relig_tidy$avg_income[relig_tidy$religion == "Agnostic"] * relig_tidy$people[relig_tidy$religion == "Agnostic"]), na.rm = TRUE) /
sum(relig_tidy$people[relig_tidy$religion == "Agnostic"], na.rm = TRUE)
sum((relig_tidy$avg_income[relig_tidy$religion == "Catholic"] * relig_tidy$people[relig_tidy$religion == "Catholic"]), na.rm = TRUE) /
sum(relig_tidy$people[relig_tidy$religion == "Catholic"], na.rm = TRUE)
📝 Si debemos elegir budismo (Buddhist
) e hinduismo (Hindu
), ¿cuál de las dos es la religión mayoritaria entre los que ganan más de 50 000$ anuales?
Code
<-
greatest_income $income_inf >= 50 & relig_tidy$religion %in% c("Buddhist", "Hindu"), ]
relig_tidy[relig_tidy
sum(greatest_income$people[greatest_income$religion == "Buddhist"], na.rm = TRUE)
sum(greatest_income$people[greatest_income$religion == "Hindu"], na.rm = TRUE)
📝 Echa un vistazo a la tabla table4b
del paquete {tidyr}
. ¿Es tidydata? En caso negativo, ¿qué falla? ¿Cómo convertirla a tidy data en caso de que no lo sea ya?
Code
|>
table4b pivot_longer(cols = "1999":"2000", names_to = "year",
values_to = "cases")
📝 Echa un vistazo a la tabla billboard
del paquete {tidyr}
. ¿Es tidydata? En caso negativo, ¿qué falla? ¿Cómo convertirla a tidy data en caso de que no lo sea ya?
Code
|>
billboard pivot_longer(cols = "wk1":"wk76",
names_to = "week",
names_prefix = "wk",
values_to = "position",
values_drop_na = TRUE)
2 🐣 Caso práctico: análisis de datos de la OMS
En el paquete {tidyr}
contamos con el dataset who2
(dataset de la Organización Mundial de la Salud - OMS)
library(tidyr)
who2
# A tibble: 7,240 × 58
country year sp_m_014 sp_m_1524 sp_m_2534 sp_m_3544 sp_m_4554 sp_m_5564
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Afghanistan 1980 NA NA NA NA NA NA
2 Afghanistan 1981 NA NA NA NA NA NA
3 Afghanistan 1982 NA NA NA NA NA NA
4 Afghanistan 1983 NA NA NA NA NA NA
5 Afghanistan 1984 NA NA NA NA NA NA
6 Afghanistan 1985 NA NA NA NA NA NA
7 Afghanistan 1986 NA NA NA NA NA NA
8 Afghanistan 1987 NA NA NA NA NA NA
9 Afghanistan 1988 NA NA NA NA NA NA
10 Afghanistan 1989 NA NA NA NA NA NA
# ℹ 7,230 more rows
# ℹ 50 more variables: sp_m_65 <dbl>, sp_f_014 <dbl>, sp_f_1524 <dbl>,
# sp_f_2534 <dbl>, sp_f_3544 <dbl>, sp_f_4554 <dbl>, sp_f_5564 <dbl>,
# sp_f_65 <dbl>, sn_m_014 <dbl>, sn_m_1524 <dbl>, sn_m_2534 <dbl>,
# sn_m_3544 <dbl>, sn_m_4554 <dbl>, sn_m_5564 <dbl>, sn_m_65 <dbl>,
# sn_f_014 <dbl>, sn_f_1524 <dbl>, sn_f_2534 <dbl>, sn_f_3544 <dbl>,
# sn_f_4554 <dbl>, sn_f_5564 <dbl>, sn_f_65 <dbl>, ep_m_014 <dbl>, …
Échale un vistazo y piensa qué cosas te podría pedir para convertirlo a tidydata.
2.1 Pregunta 1
¿Qué significan los datos? ¿Cuántas variables y observaciones tenemos?
Code
library(tidyr)
? who2
2.2 Pregunta 2
¿Es tidy data? ¿Por qué
Code
# No es tidy data porque en realidad todas las variable
# a partir de year es lo mismo: casos de tuberculosis
# Son todo casos, solo que en distintas edades o sexo o tipos
# de diagnosis, pero la variable es "cases"
2.3 Pregunta 3
Primer paso para tidy data: pivota la tabla (consejo: usa papel y boli para bocetar como debería quedar la base de datos) tal que exista una columna llamada
cases
Code
<-
who_tidy |>
who2 # fíjate que en lugar de elegir las 56 columnas
# le decimos las que NO queremos pivotar
# los nombres de columnas los mandamos a "type" (tipo de caso)
pivot_longer(cols = -(country:year),
names_to = "type",
values_to = "cases")
who_tidy
2.4 Pregunta 4
Si te fijas hay muchísimas filas que no tiene sentido mantener ya que ¡no tenemos casos! Investiga las opciones de
pivot_longer()
para ver como podemos directamente eliminarlas en el pivotaje
Code
<-
who_tidy |>
who2 # con values_drop_na = TRUE eliminamos los NA
pivot_longer(cols = -(country:year),
names_to = "type",
values_to = "cases",
values_drop_na = TRUE)
who_tidy
2.5 Pregunta 5
Si te fijas ahora en type tenemos codificada la información como diagnosis_sexo_edad. ¿Cómo separarlo en 3 columnas? Investiga tanto
separate()
como las opciones depivot_longer()
Code
# con separate
<-
who_tidy |>
who_tidy separate(col = "type", into = c("diagnosis", "sex", "age"))
# con pivot_longer
<-
who_tidy |>
who2 pivot_longer(cols = -(country:year),
names_to = c("diagnosis", "sex", "age"),
values_to = "cases",
values_drop_na = TRUE,
names_sep = "_")
who_tidy
2.6 Pregunta 6
Por último, separa en dos (age_inf, age_sup) el tramo etario (que sean números). Piensa cómo hacerlo ya que no siempre son 4 números
Code
# Usamos separate y le indicamos las posiciones, pero desde atrás
# ya que siempre el límite superior es un número de 2 cifras
# y usamos convert = TRUE para convertir a números
<-
who_tidy |>
who_tidy separate(col = "age", into = c("age_inf", "age_sup"),
sep = -2, convert = TRUE)