TP1 - tidyverse olímpico
En este práctico vamos a usar los paquetes del {tidyverse} para explorar los datos históricos de los Juegos Olímpicos desde Atenas 1896 a Rio 2016 (faltan Tokio 2020 y Pekín 2022).
Antes de empezar les recordamos que tienen que instalar los paquetes del {tidyverse} y adjuntarlo a la sesión de R ejecutando las dos líneas a continuación (si ya instalaron los paquetes del {tidyverse} no hace falta que corran la primera línea):
#install.packages("tidyverse")
library(tidyverse)
Cómo cargar los datos
Los datos históricos de los Juegos Olímpicos son un dataset de
Kaggle. Para cargarlos a su sesión de R los pueden
encontrar en el repositorio de la materia, en las carpetas
docs/Practicos/tidyverse/data
, copiarlos en su carpeta de
trabajo y leerlos utilizando la función read_csv()
del
paquete {readr}.
<- read_csv("./data/dictionary.csv")
dictionary_tbl <- read_csv("./data/summer.csv")
summer_tbl <- read_csv("./data/winter.csv") winter_tbl
Los datos
dictionary_tbl
, winter_tbl
y
summer_tbl
son tres (tristes) tibbles
que
contienen información sobre los países participantes de los juegos
Olímpicos y resultados de los juegos de invierno y de verano,
respectivamente.
Les dejamos la exploración de las observaciones y las variables a
ustedes. Recuerden que tienen funciones como str()
,
summary()
, head()
o View()
que
pueden resultar muy útiles para empezar a entender el contenido de cada
tibble
.
Las consignas
La idea es que pongan en práctica todas las funcionalidades del
tidyverse que vimos en las clases, cosas como el piping
o
los verbos de {dplyr}. Es por eso que les recomendamos que,
aunque existan métodos alternativos para obtener las respuestas a estas
consignas, intenten utilizar las herramientas que les acabamos de
mencionar.
Por supuesto que con lo que vimos en las clases no les va a alcanzar para resolver las consignas, pero para todo lo que no está en las clases existe google.
Vamos a ver qué jugo🥤les podemos sacar a estos datos…
Empecemos con algo sencillo: ¿Qué simboliza cada fila del
tibble
? ¿Es una medalla por país o por atleta?.Pista: usemos
View()
para visualizarsummer_tbl
antes de hacer ninguna operación. En la columnaAthlete
¿Qué pasa en los deportes de equipo? Si de ahora en adelante vamos a estar interesados en las medallas por país ¿Esta bien calcular las medallas totales sumando las filas deltibble
? ¿Cómo podemos hacer para solucionarlo?.Acá una propuesta (hagan lo mismo para
winter_tbl
):
# Acomodemos el tibble
<- summer_tbl %>%
summer_por_disciplina_tbl group_by(Year, City, Sport, Country, Discipline, Event, Gender, Medal) %>%
summarise() # No hace ninguna operación, simplemente se queda con una sola de las ocurrencias
# Acomodemos el tibble
<- winter_tbl %>%
winter_por_disciplina_tbl group_by(Year, City, Sport, Country, Discipline, Event, Gender, Medal) %>%
summarise() # No hace ninguna operación, simplemente se queda con una sola de las ocurrencias
Ahora que ya tenemos las medallas por país (y no por atleta 😉) para cada disciplina, usando
group_by()
y los verbos de {dplyr}, creen un nuevo tibble (oro_por_pais
) que tenga, de forma ordenada, la cantidad de medallas de oro que ganó cada país en toda la historia de los Juegos Olímpicos de verano.Pista: Si queremos ordenar algo de forma descendente en
dplyr
tenemos que usararrange(desc(variable))
.
# Solución
<- summer_por_disciplina_tbl %>%
gold_by_country filter(Medal=="Gold") %>%
group_by(Country) %>%
count(name = "N") %>% # o summarise(N = n())
arrange(desc(N))
head(gold_by_country)
#> # A tibble: 6 × 2
#> # Groups: Country [6]
#> Country N
#> <chr> <int>
#> 1 USA 979
#> 2 URS 396
#> 3 GBR 241
#> 4 FRA 202
#> 5 CHN 200
#> 6 ITA 197
- ¿Y si ahora queremos ver cuántas de Oro, de Plata y de Bronce? ¿Cómo
deberíamos modificar el pipe
%>%
de análisis?
# Solución
<- summer_por_disciplina_tbl %>%
medal_by_country group_by(Country, Medal) %>%
count(name = "N")# o summarise(N = n())
head(medal_by_country)
#> # A tibble: 6 × 3
#> # Groups: Country, Medal [6]
#> Country Medal N
#> <chr> <chr> <int>
#> 1 AFG Bronze 2
#> 2 AHO Silver 1
#> 3 ALG Bronze 8
#> 4 ALG Gold 5
#> 5 ALG Silver 2
#> 6 ANZ Bronze 5
- ¿Y para quedarnos con los países en
oro_por_pais
con más de 5 medallas de oro? ¿Está Argentina🇦🇷 (ARG
) en ese grupo?
# Solución
<- summer_por_disciplina_tbl %>%
gold_by_country filter(Medal=="Gold") %>%
group_by(Country) %>%
count(name = "N") %>% # o summarise(N = n())
filter(N>5)
head(gold_by_country)
#> # A tibble: 6 × 2
#> # Groups: Country [6]
#> Country N
#> <chr> <int>
#> 1 ARG 18
#> 2 AUS 141
#> 3 AUT 18
#> 4 AZE 6
#> 5 BEL 37
#> 6 BLR 13
¿Quién ganó más medallas de oro en Hockey sobre hielo (
Ice Hockey
) masculino, Canadá (CAN
) o la Unión Soviética (URS
)?Pista: Para filtrar una columna de acuerdo a varios posibles valores discretos les recomiendo investigar el operador %in%.
# Solución
<- winter_por_disciplina_tbl %>%
medallas_hockey_tbl filter(Country %in% c("URS", "CAN")) %>%
filter(Discipline == "Ice Hockey") %>%
filter(Medal == "Gold") %>%
filter(Gender == "Men") %>%
group_by(Country) %>%
count(name = "N") # o summarise(N = n())
head(medallas_hockey_tbl)
#> # A tibble: 2 × 2
#> # Groups: Country [2]
#> Country N
#> <chr> <int>
#> 1 CAN 8
#> 2 URS 7
Armemos un
tibble
con los nombres de los medallistas olímpicos argentinos en deportes acuáticos y la disciplina, evento, juego y medalla que ganaron.Pista: Para seleccionar más de una columna hay que hacer una lista usando
c()
y se recomienda utilizar all_of().
# Solución
<- summer_tbl %>%
nombres_natacion_tbl filter(Sport == "Aquatics") %>%
filter(Country == "ARG") %>%
select(all_of(c("Year", "Athlete", "Discipline", "Event", "Medal")))
nombres_natacion_tbl#> # A tibble: 3 × 5
#> Year Athlete Discipline Event Medal
#> <dbl> <chr> <chr> <chr> <chr>
#> 1 1928 ZORRILLA, Victoriano Swimming 400M Freestyle Gold
#> 2 1936 CAMPBELL, Jeanette Morven Swimming 100M Freestyle Silver
#> 3 2004 BARDACH, Georgina Swimming 400M Individual Medley Bronze
¿Cuáles son los tres países con más medallas de oro en total (juegos de invierno y verano)?
Pista 1: para combinar dos
tibbles
con las mismas columnas pueden usar bind_rows().Pista 2: Para quedarse con los tres primeros valores pueden usar la función slice_head() con
n = 3
.
# Solución
<- winter_por_disciplina_tbl %>%
top_3_tbl bind_rows(summer_por_disciplina_tbl) %>%
filter(Medal == "Gold") %>%
group_by(Country) %>%
count(name = "N") %>% # o summarise(N = n())
arrange(desc(N)) %>%
slice_head(n = 3)
head(top_3_tbl)
#> # A tibble: 6 × 2
#> # Groups: Country [6]
#> Country N
#> <chr> <int>
#> 1 ALG 5
#> 2 ANZ 3
#> 3 ARG 18
#> 4 ARM 1
#> 5 AUS 146
#> 6 AUT 79
Aprovechemos los datos de
dictionary_tbl
para pensar un poco en la cantidad de medallas por millón de habitantes. Armemos untibble
que contenga la cantidad de medallas per cápita por país. ¿Qué pasó con la Unión Soviética (URS
)?Pista 1: Para juntar dos
tibbles
pueden usar la función inner_join()Pista 2: Para descartar las filas con valores
NA
pueden usar la función drop_na()
# Solución
<- summer_por_disciplina_tbl %>%
medallas_per_million_tbl rbind(winter_por_disciplina_tbl) %>%
group_by(Country) %>%
count(name = "Total_Medals") %>% # o summarise(Total_Medals = n()) %>%
rename("Code" = "Country") %>%
left_join(dictionary_tbl) %>%
drop_na() %>%
mutate(medals_per_million = Total_Medals/Population * 1e6) %>%
select(all_of(c("Country", "medals_per_million"))) %>%
arrange(desc(medals_per_million))
head(medallas_per_million_tbl)
#> # A tibble: 6 × 3
#> # Groups: Code [6]
#> Code Country medals_per_million
#> <chr> <chr> <dbl>
#> 1 NOR Norway 92.4
#> 2 FIN Finland 84.5
#> 3 SWE Sweden 63.9
#> 4 HUN Hungary 49.5
#> 5 SUI Switzerland 39.5
#> 6 AUT Austria 35.9
¿Cuántos medallistas olímpicos de invierno que ganaron bronce tienen de nombre John?
Opción 1: La función
str_split()
de {stringr} nos separa un string en base a un separador que les damos. Por ejemplostr_split("Juan Perez", pattern = " ")
nos de la lista"Juan" "Perez"
, y de esta forma accedemos a su primer elementostr_split("Juan Perez", pattern = " ")[[1]][1]
.Opción 2: La función
str_detect()
de {stringr} nos devuelve unTRUE
si encuentra un patrón en el texto y unFALSE
si no. Por ejemplo,str_detect("Juan Perez", "Juan", negate = FALSE)
devuelveTRUE
ystr_detect("Pedro Perez", "Juan", negate = FALSE)
devuelveFALSE
.Recuerden también usar el verbo
mutate()
.
# Solución
<- winter_tbl %>%
juanes_tbl filter(Medal == "Bronze") %>%
mutate(is_jhon = str_detect(Athlete, "John", negate = FALSE)) %>%
filter(is_jhon)
head(juanes_tbl)
#> # A tibble: 6 × 10
#> Year City Sport Discipline Athlete Country Gender Event Medal is_jhon
#> <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <lgl>
#> 1 1928 St.Moritz Skat… Speed ska… FARREL… USA Men 500M Bron… TRUE
#> 2 1928 St.Moritz Skii… Nordic Co… SNERSR… NOR Men Indi… Bron… TRUE
#> 3 1932 Lake Placid Bobs… Bobsleigh HEATON… USA Men Two-… Bron… TRUE
#> 4 1936 Garmisch Pa… Ice … Ice Hockey GARRIS… USA Men Ice … Bron… TRUE
#> 5 1936 Garmisch Pa… Ice … Ice Hockey LAX, J… USA Men Ice … Bron… TRUE
#> 6 1936 Garmisch Pa… Ice … Ice Hockey SHAUGH… USA Men Ice … Bron… TRUE