Tidyverse (Wickham et al. 2019) es una colección de paquetes que nos permiten manipular juegos de datos para hacer análisis simples, reproducibles y ordenados. Constantemente los paquetes dentro de tidyverse son actualizados, para ello te recomiendo visitar la página de tidyverse para estar al día con las noticias.
Para instalar tidyverse en tu equipo corre la siguiente linea de código:
Sigue las instrucciones en la consola de R y una vez que se haya instalado carga los paquetes usando la siguiente línea de código:
En la consola de R observa como es que se han cargado los paquetes de ggplot, tibble, tidyr, readr, purr, dplyr, stringr y forcats.
Solo necesitas instalar una sola vez el paquete de tidyverse. Cada vez que inicies una nueva sesión en RStudio, no es necesario que lo vuelvas a instalar.
En tidyverse trabajar con dataframes es problemático por: -
Al teclear su nombre se despliegan las primeras 1000 o 999 filas
- Las columnas con datos de clase caracter son
codificadas a factores lo cual dificulta su manejo
- Las columnas o variables no pueden ser
nombradas con caracteres o símbolos especiales
- Almacenan nombres de filas o rownames()
lo cual
incrementa su complejidad
- Problemas con datos faltantes
Para solucionar estos “problemas” tidyverse desarrolló una tabla de
datos más flexible conocida como tibble()
con el eslogan
Los Tibbles hacen menos y se comportan mejor. Para generar un
tibble, existen distintas maneras:
Generando un tibble con la función tibble()
#Genera un tibble de manera similar al dataframe
tibble(Aerolinea = c("Aeromexico", "KLM", "Lufthansa", "Avianca"), Pais = c("Mexico", "Paises Bajos", "Alemania", "Colombia"), Vuelos_anuales = c(300, 1200, 1500, 200), Pista = 23)
Aerolinea | Pais | Vuelos_anuales | Pista |
---|---|---|---|
Aeromexico | Mexico | 300 | 23 |
KLM | Paises Bajos | 1200 | 23 |
Lufthansa | Alemania | 1500 | 23 |
Avianca | Colombia | 200 | 23 |
Observa como para la columna de la pista no fue
necesario repetir 4 veces el número 23. tibble()
entiende
que se trata del mismo valor para todas las filas
Convirtiendo un dataframe existente a un tibble usando la función
as_tibble()
## [1] "data.frame"
## # A tibble: 150 × 5
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## <dbl> <dbl> <dbl> <dbl> <fct>
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
## 7 4.6 3.4 1.4 0.3 setosa
## 8 5 3.4 1.5 0.2 setosa
## 9 4.4 2.9 1.4 0.2 setosa
## 10 4.9 3.1 1.5 0.1 setosa
## # ℹ 140 more rows
¿Cuál tabla te pareció más útil? ¿Dataframe? ¿Tibble? Utiliza la que creas más conveniente para tus análisis
El paquete de dplyr utiliza una sintaxis a base verbos (en inglés) que permiten manipular cuadros de datos o tibbles para extraer información de una manera amigable. Existen diversas funciones (o verbos) en el paquete dplyr y son:
select()
Selecciona columnas de cuadros de datos o
tibbles de manera específicafilter()
Filtra datos de una o varias columnas que
cumplen o no alguna condiciónmutate()
Crea nuevas columnas a partir de datos
existentesarrange()
Ordena los datos de manera ascendente o
descendente con respecta a una columnaAunque estas sean las funciones más empleadas de dplyr existen otras
que de manera más específica nos permiten manipular y analizar los
datos. En el transcurso las irémos mencionando.
Una de las principales utilidades de dplyr (y de todos los paquetes de
tidyverse) es que podemos hacer uso de tuberias o
pipes para ligar los resultados de forma consecutiva al aplicar
varias funciones. En dplyr el operador pipe se escribe como
%>%
y la sintaxis es la siguiente:
funcion_1(objeto) %>% funcion_2() %>% funcion_3()
El resultado de la función 1 se transfiere y evalúa con la función 2. Posteriormente, el resultado de la función 2 se transfiere a la función 3. En los argumentos de la función 1 se evalúa el objeto (data frame o tibble) y se omite en las siguientes funciones. Es muy importante que haya una lógica en la secuencia de las funciones para que el pipe no se rompa.
La función select()
permite extraer una o varias
columnas de un cuadro de datos o tibble para su análisis en concreto. La
sintaxis es la siguiente:
select(objeto, columna1, columna2, columna3, ..., columnaN)
Revisemos las columnas la base de datos y seleccionemos algunas
usando la función select()
## [1] "name" "height" "mass" "hair_color" "skin_color"
## [6] "eye_color" "birth_year" "sex" "gender" "homeworld"
## [11] "species" "films" "vehicles" "starships"
#Selecciona las que corresponden al nombre, color de cabello, sexo, genero, especie y lugar de residencia
select(starwars, name, height, mass, sex, species)
## # A tibble: 87 × 5
## name height mass sex species
## <chr> <int> <dbl> <chr> <chr>
## 1 Luke Skywalker 172 77 male Human
## 2 C-3PO 167 75 none Droid
## 3 R2-D2 96 32 none Droid
## 4 Darth Vader 202 136 male Human
## 5 Leia Organa 150 49 female Human
## 6 Owen Lars 178 120 male Human
## 7 Beru Whitesun lars 165 75 female Human
## 8 R5-D4 97 32 none Droid
## 9 Biggs Darklighter 183 84 male Human
## 10 Obi-Wan Kenobi 182 77 male Human
## # ℹ 77 more rows
El resultado es un nuevo data frame o tibble con los datos de las columnas seleccionadas
En ocasiones queremos realizar la operación inversa, es decir omitir ciertas columnas. Por ejemplo, eliminemos las últimas tres columnas de la base de datos:
#Para eliminar columnas coloca los nombres dentro de un vector y un signo negativo o guión alto antes del vector
select(starwars, -c(films, vehicles, starships))
## # A tibble: 87 × 11
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Luke Sk… 172 77 blond fair blue 19 male mascu…
## 2 C-3PO 167 75 <NA> gold yellow 112 none mascu…
## 3 R2-D2 96 32 <NA> white, bl… red 33 none mascu…
## 4 Darth V… 202 136 none white yellow 41.9 male mascu…
## 5 Leia Or… 150 49 brown light brown 19 fema… femin…
## 6 Owen La… 178 120 brown, gr… light blue 52 male mascu…
## 7 Beru Wh… 165 75 brown light blue 47 fema… femin…
## 8 R5-D4 97 32 <NA> white, red red NA none mascu…
## 9 Biggs D… 183 84 black light brown 24 male mascu…
## 10 Obi-Wan… 182 77 auburn, w… fair blue-gray 57 male mascu…
## # ℹ 77 more rows
## # ℹ 2 more variables: homeworld <chr>, species <chr>
Nota como dentro del vector los nombres de las columnas, a pesar de ser caracteres, no fue necesario utilizar comillas. Esta es una característica de los paquetes de tidyverse que dentro de su sintaxis omiten el uso de comillas para datos que ya se encuentran dentro del pipe.
La función `select() no está vectorizada, es decir el resultado no es un vector.
Cuando queremos seleccionar una columna de un data frame o tibble y
que el resultado sea un vector, usemos la función
pull()
:
#Selecciona la columna del nombre de los personajes de starwars y que el resultado sea un vector
pull(my_starwars, height)
#Compara el resultado con el uso del operador $
my_starwars$height
Otra operación común con las columnas de un dataframe o tibble es el
reordenamiento de columnas. dplyr nos ofrece una alternativa más
sencilla a la sintaxis primitiva de R con la función
relocate()
. La sintaxis es la siguiente:
relocate(objeto, columna_1, columna_2, ..., columna_N)
En donde nosotros podemos indicarle a dplyr cuál es el nuevo orden de las columnas en el data frame. Ejemplo, reordena tabla de mi_base de manera que el Peso_1 y Talla_Cm_1 sean las primeras dos columnas:
## # A tibble: 87 × 11
## name height mass species hair_color skin_color eye_color birth_year sex
## <chr> <int> <dbl> <chr> <chr> <chr> <chr> <dbl> <chr>
## 1 Luke S… 172 77 Human blond fair blue 19 male
## 2 C-3PO 167 75 Droid <NA> gold yellow 112 none
## 3 R2-D2 96 32 Droid <NA> white, bl… red 33 none
## 4 Darth … 202 136 Human none white yellow 41.9 male
## 5 Leia O… 150 49 Human brown light brown 19 fema…
## 6 Owen L… 178 120 Human brown, gr… light blue 52 male
## 7 Beru W… 165 75 Human brown light blue 47 fema…
## 8 R5-D4 97 32 Droid <NA> white, red red NA none
## 9 Biggs … 183 84 Human black light brown 24 male
## 10 Obi-Wa… 182 77 Human auburn, w… fair blue-gray 57 male
## # ℹ 77 more rows
## # ℹ 2 more variables: gender <chr>, homeworld <chr>
Ejercicio 1
Emplea la base de datos my_starwars:
- Obten el nombre de las columnas del tibble
- Selecciona las columnas relacionadas con el color de cabello, color de ojos, año de nacimiento y sexo
- Selecciona las todas columnas excepto las que se asocian con la altura, masa y la especie
- Relocaliza la columna de la especie entre la masa y el color de cabello
filter()
es una alternativa más amigable a las funciones
which()
y subset()
para extraer datos que
cumplan con ciertas condiciones. La sintaxis es la siguiente:
filter(objeto, condicion_1, condicion_2, condicion_3, ..., condicion_N)
El resultado de aplicar filter()
es un data frame o
tibble con las filas que cumplen la o las condiciones. Por ejemplo,
extraigamos los datos de aquellos personajes de starwars con una altura
mayor a la media:
## [1] NA
## # A tibble: 43 × 11
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Darth V… 202 136 none white yellow 41.9 male mascu…
## 2 Biggs D… 183 84 black light brown 24 male mascu…
## 3 Obi-Wan… 182 77 auburn, w… fair blue-gray 57 male mascu…
## 4 Anakin … 188 84 blond fair blue 41.9 male mascu…
## 5 Wilhuff… 180 NA auburn, g… fair blue 64 male mascu…
## 6 Chewbac… 228 112 brown unknown blue 200 male mascu…
## 7 Han Solo 180 80 brown fair brown 29 male mascu…
## 8 Jek Ton… 180 110 brown fair blue NA male mascu…
## 9 Boba Fe… 183 78.2 black fair brown 31.5 male mascu…
## 10 IG-88 200 140 none metal red 15 none mascu…
## # ℹ 33 more rows
## # ℹ 2 more variables: homeworld <chr>, species <chr>
Recuerda hacer uso de los operadores relacionales ==, !=, >, <, >=, <= y de los nexos | y & para comparar multiples condiciones
filter()
permite evaluar dos o mas condiciones, por
ejemplo seleccionemos aquellos personajes mayores a 178 cm y que sean
“Humanos”
## # A tibble: 16 × 11
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Darth V… 202 136 none white yellow 41.9 male mascu…
## 2 Biggs D… 183 84 black light brown 24 male mascu…
## 3 Obi-Wan… 182 77 auburn, w… fair blue-gray 57 male mascu…
## 4 Anakin … 188 84 blond fair blue 41.9 male mascu…
## 5 Wilhuff… 180 NA auburn, g… fair blue 64 male mascu…
## 6 Han Solo 180 80 brown fair brown 29 male mascu…
## 7 Jek Ton… 180 110 brown fair blue NA male mascu…
## 8 Boba Fe… 183 78.2 black fair brown 31.5 male mascu…
## 9 Qui-Gon… 193 89 brown fair blue 92 male mascu…
## 10 Mace Wi… 188 84 none dark brown 72 male mascu…
## 11 Gregar … 185 85 black dark brown NA male mascu…
## 12 Cliegg … 183 NA brown fair blue 82 male mascu…
## 13 Dooku 193 80 white fair brown 102 male mascu…
## 14 Bail Pr… 191 NA black tan brown 67 male mascu…
## 15 Jango F… 183 79 black tan brown 66 male mascu…
## 16 Raymus … 188 79 brown light brown NA male mascu…
## # ℹ 2 more variables: homeworld <chr>, species <chr>
¿Cómo podemos evaluar dos funciones de dplyr? A través de un
pipe utilicemos las
funciones filter()
y select()
para filtrar
datos de las personajes que tengan una masa por abajo de la media (77.7
kg). A partir de los nuevos datos seleccionemos el nombre, la altura y
la masa:
filter(my_starwars, mass < 77.7) %>% #Filtra los datos empleando la función filter
select(name, height, mass) #Selecciona las columnas name, height, species y sex
## # A tibble: 27 × 3
## name height mass
## <chr> <int> <dbl>
## 1 Luke Skywalker 172 77
## 2 C-3PO 167 75
## 3 R2-D2 96 32
## 4 Leia Organa 150 49
## 5 Beru Whitesun lars 165 75
## 6 R5-D4 97 32
## 7 Obi-Wan Kenobi 182 77
## 8 Greedo 173 74
## 9 Wedge Antilles 170 77
## 10 Yoda 66 17
## # ℹ 17 more rows
¿Es posible filtrar datos con dplyr a partir de valores estadísticos
por grupo? La función filter()
puede tener diferentes
resultados dependiendo de la pregunta que tengamos en mente. Por
ejemplo, nos puede interesar seleccionar aquellos personajes que cumplan
con una condición grupal. En la base de datos estamos interesados en
seleccionar aquelos personajes que tengan una masa por
arriba del promedio de su sexo:
#Obten la media de la masa por cada genero
group_by(starwars, sex) %>% #Agrupa los datos por genero usando la función group_by
summarise(masa = mean(mass)) #La funcion summarise genera un dataframe con una columna en la cual se resumen los resultados de cada grupo del parametro que se mide (promedio de la masa)
## # A tibble: 5 × 2
## sex masa
## <chr> <dbl>
## 1 female NA
## 2 hermaphroditic 1358
## 3 male NA
## 4 none NA
## 5 <NA> NA
#Emplea la función group_by para agrupar los datos por genero
group_by(my_starwars, sex) %>%
filter(mass > mean(mass, na.rm = T)) #Filtra los datos seleccionando aquellos que esten por arriba de la media de la masa tratando a cada genero por separado
## # A tibble: 26 × 11
## # Groups: sex [3]
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 C-3PO 167 75 <NA> gold yellow 112 none mascu…
## 2 Darth V… 202 136 none white yellow 41.9 male mascu…
## 3 Owen La… 178 120 brown, gr… light blue 52 male mascu…
## 4 Beru Wh… 165 75 brown light blue 47 fema… femin…
## 5 Biggs D… 183 84 black light brown 24 male mascu…
## 6 Anakin … 188 84 blond fair blue 41.9 male mascu…
## 7 Chewbac… 228 112 brown unknown blue 200 male mascu…
## 8 Jek Ton… 180 110 brown fair blue NA male mascu…
## 9 IG-88 200 140 none metal red 15 none mascu…
## 10 Bossk 190 113 none green red 53 male mascu…
## # ℹ 16 more rows
## # ℹ 2 more variables: homeworld <chr>, species <chr>
La función group_by()
identifica los grupos en variables
categóricas y con funciones de dplyr subsecuentes podemos conocer las
características de cada grupo con respecto a una o más variables.
Ejercicio 2
Utiliza la base de datos my_starwars y realiza lo siguiente:
- Filtra todos los personajes que tengan una masa menor a 80 kg
- Del resultado anterior filtra todos aquellos nacidos en Tatooin *5. Filtra los resultados de los personajes (femenino y masculino) que estén por abajo de la media, por sexo, de altura.
mutate()
es una función de dplyr que permite crear
nuevas columnas o modificar las existentes. Es una manera alternativa al
uso del operador $ para crear o modificar
columnas. La sintaxis es:
mutate(objeto, nueva_columna = operaciones)
Por ejemplo, convirtammos la masa de los personajes en kg a g el índice de masa corporal de los pacientes*:
#Modifica la columna de la masa y convierte los valores de kg a g
mutate(my_starwars, mass = mass*1000)
## # A tibble: 87 × 11
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Luke S… 172 77000 blond fair blue 19 male mascu…
## 2 C-3PO 167 75000 <NA> gold yellow 112 none mascu…
## 3 R2-D2 96 32000 <NA> white, bl… red 33 none mascu…
## 4 Darth … 202 136000 none white yellow 41.9 male mascu…
## 5 Leia O… 150 49000 brown light brown 19 fema… femin…
## 6 Owen L… 178 120000 brown, gr… light blue 52 male mascu…
## 7 Beru W… 165 75000 brown light blue 47 fema… femin…
## 8 R5-D4 97 32000 <NA> white, red red NA none mascu…
## 9 Biggs … 183 84000 black light brown 24 male mascu…
## 10 Obi-Wa… 182 77000 auburn, w… fair blue-gray 57 male mascu…
## # ℹ 77 more rows
## # ℹ 2 more variables: homeworld <chr>, species <chr>
La función arrange()
es equivalente a
sort()
de la unidad de vectores. Con
arrange()
podemos organizar datos de manera ascendente o
descendente respecto a una columna del data frame o tibble. La sintaxis
es la siguiente:
arrange(objeto, columna)
Por ejemplo, nos interesa ordenar los datos de los personajes de la base con respecto a su año de nacimiento:
## # A tibble: 87 × 11
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Wicket … 88 20 brown brown brown 8 male mascu…
## 2 IG-88 200 140 none metal red 15 none mascu…
## 3 Luke Sk… 172 77 blond fair blue 19 male mascu…
## 4 Leia Or… 150 49 brown light brown 19 fema… femin…
## 5 Wedge A… 170 77 brown fair hazel 21 male mascu…
## 6 Plo Koon 188 80 none orange black 22 male mascu…
## 7 Biggs D… 183 84 black light brown 24 male mascu…
## 8 Han Solo 180 80 brown fair brown 29 male mascu…
## 9 Lando C… 177 79 black dark brown 31 male mascu…
## 10 Boba Fe… 183 78.2 black fair brown 31.5 male mascu…
## # ℹ 77 more rows
## # ℹ 2 more variables: homeworld <chr>, species <chr>
O de forma inversa, deseamos ordenar los datos de los pacientes con respecto a la edad de forma descendente:
## # A tibble: 87 × 11
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Yoda 66 17 white green brown 896 male mascu…
## 2 Jabba D… 175 1358 <NA> green-tan… orange 600 herm… mascu…
## 3 Chewbac… 228 112 brown unknown blue 200 male mascu…
## 4 C-3PO 167 75 <NA> gold yellow 112 none mascu…
## 5 Dooku 193 80 white fair brown 102 male mascu…
## 6 Qui-Gon… 193 89 brown fair blue 92 male mascu…
## 7 Ki-Adi-… 198 82 white pale yellow 92 male mascu…
## 8 Finis V… 170 NA blond fair blue 91 male mascu…
## 9 Palpati… 170 75 grey pale yellow 82 male mascu…
## 10 Cliegg … 183 NA brown fair blue 82 male mascu…
## # ℹ 77 more rows
## # ℹ 2 more variables: homeworld <chr>, species <chr>
La opcióndesc()
es equivalente adecreasing =
de la funciónsort()
Como lo hemos visto dplyr es un paquete al cual se le puede extraer mucho jugo para realizar análisis de datos. Gracias a su sintaxis simple y al uso de pipes los análisis se vuelven altamente reproducibles y simples.
Tidyr es otro paquete de tidyverse que permite estructurar y organizar datos de una manera más simple. Como lo hemos visto, una tabla de datos organizada se analiza con una facilidad mayor. Además, su estructura organizada nos permite entender o comprender su contenido.
Tidyr nos ofrece una serie de funciones para estructurar nuestros datos en tibbles. Exploremos algunas de sus funciones:
Al crear bases de datos y tablas es comun encontrar datos faltantes en algunas columnas. Para ello, la celda no debe dejarse vacía y se debe de llenar con el valor NA. Existen diversas maneras de verificar la presencia de valores NA en las columnas de una tabla:
##La función is.na() nos devuelve un vector lógico indicando TRUE si hay un valor NA o FALSE lo contrario
is.na(billboard)
##Al combinar la función table() nos devuelve la cantidad de valores TRUE (NA) o FALSE (no NA)
table(is.na(billboard$wk5))
Para ciertos análisis estadísticos, las funciones no tienen la capacidad de procesar los datos NA. Tidyr nos ofrece tres funciones que permiten recodificar o remover datos NA:
drop_na()
es una función que elimina las filas que
presentan un dato NA en alguna de las columnas que le
especifiquemos. La sintaxis es la siguiente:
drop_na(objeto, columna)
Eliminemos los datos NA presentes en la columna de wk5:
## # A tibble: 292 × 79
## artist track date.entered wk1 wk2 wk3 wk4 wk5 wk6 wk7 wk8
## <chr> <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2 Pac Baby… 2000-02-26 87 82 72 77 87 94 99 NA
## 2 3 Doors D… Kryp… 2000-04-08 81 70 68 67 66 57 54 53
## 3 3 Doors D… Loser 2000-10-21 76 76 72 69 67 65 55 59
## 4 504 Boyz Wobb… 2000-04-15 57 34 25 17 17 31 36 49
## 5 98^0 Give… 2000-08-19 51 39 34 26 26 19 2 2
## 6 A*Teens Danc… 2000-07-08 97 97 96 95 100 NA NA NA
## 7 Aaliyah I Do… 2000-01-29 84 62 51 41 38 35 35 38
## 8 Aaliyah Try … 2000-03-18 59 53 38 28 21 18 16 14
## 9 Adams, Yo… Open… 2000-08-26 76 76 74 69 68 67 61 58
## 10 Adkins, T… More 2000-04-29 84 84 75 73 73 69 68 65
## # ℹ 282 more rows
## # ℹ 68 more variables: wk9 <dbl>, wk10 <dbl>, wk11 <dbl>, wk12 <dbl>,
## # wk13 <dbl>, wk14 <dbl>, wk15 <dbl>, wk16 <dbl>, wk17 <dbl>, wk18 <dbl>,
## # wk19 <dbl>, wk20 <dbl>, wk21 <dbl>, wk22 <dbl>, wk23 <dbl>, wk24 <dbl>,
## # wk25 <dbl>, wk26 <dbl>, wk27 <dbl>, wk28 <dbl>, wk29 <dbl>, wk30 <dbl>,
## # wk31 <dbl>, wk32 <dbl>, wk33 <dbl>, wk34 <dbl>, wk35 <dbl>, wk36 <dbl>,
## # wk37 <dbl>, wk38 <dbl>, wk39 <dbl>, wk40 <dbl>, wk41 <dbl>, wk42 <dbl>, …
fill
es una función que nos permite llenar las celdas NA
utilizando el primer valor que encuentre previamente a la celda NA
## # A tibble: 317 × 79
## artist track date.entered wk1 wk2 wk3 wk4 wk5 wk6 wk7 wk8
## <chr> <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2 Pac Baby… 2000-02-26 87 82 72 77 87 94 99 NA
## 2 2Ge+her The … 2000-09-02 91 87 92 NA 87 NA NA NA
## 3 3 Doors D… Kryp… 2000-04-08 81 70 68 67 66 57 54 53
## 4 3 Doors D… Loser 2000-10-21 76 76 72 69 67 65 55 59
## 5 504 Boyz Wobb… 2000-04-15 57 34 25 17 17 31 36 49
## 6 98^0 Give… 2000-08-19 51 39 34 26 26 19 2 2
## 7 A*Teens Danc… 2000-07-08 97 97 96 95 100 NA NA NA
## 8 Aaliyah I Do… 2000-01-29 84 62 51 41 38 35 35 38
## 9 Aaliyah Try … 2000-03-18 59 53 38 28 21 18 16 14
## 10 Adams, Yo… Open… 2000-08-26 76 76 74 69 68 67 61 58
## # ℹ 307 more rows
## # ℹ 68 more variables: wk9 <dbl>, wk10 <dbl>, wk11 <dbl>, wk12 <dbl>,
## # wk13 <dbl>, wk14 <dbl>, wk15 <dbl>, wk16 <dbl>, wk17 <dbl>, wk18 <dbl>,
## # wk19 <dbl>, wk20 <dbl>, wk21 <dbl>, wk22 <dbl>, wk23 <dbl>, wk24 <dbl>,
## # wk25 <dbl>, wk26 <dbl>, wk27 <dbl>, wk28 <dbl>, wk29 <dbl>, wk30 <dbl>,
## # wk31 <dbl>, wk32 <dbl>, wk33 <dbl>, wk34 <dbl>, wk35 <dbl>, wk36 <dbl>,
## # wk37 <dbl>, wk38 <dbl>, wk39 <dbl>, wk40 <dbl>, wk41 <dbl>, wk42 <dbl>, …