Octavo Encuentro. Aprendiendo a Programar en 30 lecciones

Octavo encuentro

By Yanina Bellini Saibene in Español rstats Education 100DaysToOffload

May 1, 2024

En esta clase volvemos a trabajar con los conjuntos de datos y las preguntas que nos hicimos. Vamos a convertir algunos tipos de datos y trabajar con characteres para contestar dos preguntas y hacer un grafico.

Preguntas para (mas adelante) ahora.

En el quinto encuentro dejamos una serie de preguntas para mas adelante. Hoy vamos a seleccionar de ese listado y vamos a resolverlas

  • Copas: ordenar de mayor a menor o al revez la audiencia de los mundiales.

  • Jugadores:

    • ordenar los jugadores por cantidad de goles.
    • todos los jugadores que metieron 1 o mas goles en el segundo tiempo.

Ordenar las copas por audiencia.

El conjunto de datos copas tiene una columna llamada Attendance que contiene la cantidad de gente que fue a ver los partidos a los estadios.

La funcion para ordenar es arrange y si la usamos este es el resultado que obtenemos:

copas %>% 
  arrange(Attendance)

# A tibble: 20 × 10
   Year       Country      Winner     `Runners-Up`   Third   Fourth GoalsScored QualifiedTeams MatchesPlayed Attendance
   <date>     <chr>        <chr>      <chr>          <chr>   <chr>        <int>          <int>         <int> <chr>     
 1 1950-01-01 Brazil       Uruguay    Brazil         Sweden  Spain           88             13            22 1.045.246 
 2 1978-01-01 Argentina    Argentina  Netherlands    Brazil  Italy          102             16            38 1.545.791 
 3 1966-01-01 England      England    Germany FR     Portug… Sovie…          89             16            32 1.563.135 
 4 1970-01-01 Mexico       Brazil     Italy          German… Urugu…          95             16            32 1.603.975 
 5 1974-01-01 Germany      Germany FR Netherlands    Poland  Brazil          97             16            38 1.865.753 
 6 1982-01-01 Spain        Italy      Germany FR     Poland  France         146             24            52 2.109.723 
 7 1986-01-01 Mexico       Argentina  Germany FR     France  Belgi…         132             24            52 2.394.031 
 8 1990-01-01 Italy        Germany FR Argentina      Italy   Engla…         115             24            52 2.516.215 
 9 2002-01-01 Korea/Japan  Brazil     Germany        Turkey  Korea…         161             32            64 2.705.197 
10 1998-01-01 France       France     Brazil         Croatia Nethe…         171             32            64 2.785.100 
11 2010-01-01 South Africa Spain      Netherlands    Germany Urugu…         145             32            64 3.178.856 
12 2006-01-01 Germany      Italy      France         Germany Portu…         147             32            64 3.359.439 
13 2014-01-01 Brazil       Germany    Argentina      Nether… Brazil         171             32            64 3.386.810 
14 1994-01-01 USA          Brazil     Italy          Sweden  Bulga…         141             24            52 3.587.538 
15 1934-01-01 Italy        Italy      Czechoslovakia Germany Austr…          70             16            17 363.000   
16 1938-01-01 France       Italy      Hungary        Brazil  Sweden          84             15            18 375.700   
17 1930-01-01 Uruguay      Uruguay    Argentina      USA     Yugos…          70             13            18 590.549   
18 1954-01-01 Switzerland  Germany FR Hungary        Austria Urugu…         140             16            26 768.607   
19 1958-01-01 Sweden       Brazil     Sweden         France  Germa…         126             16            35 819.810   
20 1962-01-01 Chile        Brazil     Czechoslovakia Chile   Yugos…          89             16            32 893.172   
> 
  

Como podemos ver, el orden no es el esperado si la variable fuera numerica, ese orden corresponde a un orden alfabetico. Por lo que el problema esta en el tipo de dato que tiene esa columna. Al importar los datos leyendo el CSV lo hace como caracter. Cuando intentamos asignar el tipo correcto en la lectura de los datos no pudimos lograrlo:

  • la columna se leia con todos valores nulos.
  • la columna se leia con datos pero contenia valores erroneos.

Analicemos los datos de esa columna para determinar que esta pasando:

glimpse(copas)

Rows: 20
Columns: 10
$ Year           <date> 1930-01-01, 1934-01-01, 1938-01-01, 1950-01-01, 1954-01-01, 1958-01-01, 1962-01-01, 1966-01-0$ Country        <chr> "Uruguay", "Italy", "France", "Brazil", "Switzerland", "Sweden", "Chile", "England", "Mexico",…
$ Winner         <chr> "Uruguay", "Italy", "Italy", "Uruguay", "Germany FR", "Brazil", "Brazil", "England", "Brazil",…
$ `Runners-Up`   <chr> "Argentina", "Czechoslovakia", "Hungary", "Brazil", "Hungary", "Sweden", "Czechoslovakia", "Ge…
$ Third          <chr> "USA", "Germany", "Brazil", "Sweden", "Austria", "France", "Chile", "Portugal", "Germany FR", …
$ Fourth         <chr> "Yugoslavia", "Austria", "Sweden", "Spain", "Uruguay", "Germany FR", "Yugoslavia", "Soviet Uni…
$ GoalsScored    <int> 70, 70, 84, 88, 140, 126, 89, 89, 95, 97, 102, 146, 132, 115, 141, 171, 161, 147, 145, 171
$ QualifiedTeams <int> 13, 16, 15, 13, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 32, 32, 32, 32, 32
$ MatchesPlayed  <int> 18, 17, 18, 22, 26, 35, 32, 32, 32, 38, 38, 52, 52, 52, 52, 64, 64, 64, 64, 64

$ Attendance     <chr> "590.549", "363.000", "375.700", "1.045.246", "768.607", "819.810", "893.172", "1.563.135", "1…
> 

Los valores en Attendance son numeros que estan usando el punto como separador de miles. Y es por eso que son leidos como texto en vez de numeros.

El paquete readr tiene una funcion llamada parse_number que extrae los numeros. Esto elimina cualquier carácter no numérico antes o después del primer número. El separador de miles especificado por la configuración regional se ignora dentro del número. Veamos que hace esta funcion:

copas %>% 
  mutate(asistencia = parse_number(Attendance))

# A tibble: 20 × 11
   Year       Country   Winner `Runners-Up` Third Fourth GoalsScored QualifiedTeams MatchesPlayed Attendance asistencia
   <date>     <chr>     <chr>  <chr>        <chr> <chr>        <int>          <int>         <int> <chr>           <dbl>
 1 1930-01-01 Uruguay   Urugu… Argentina    USA   Yugos…          70             13            18 590.549        591.  
 2 1934-01-01 Italy     Italy  Czechoslova… Germ… Austr…          70             16            17 363.000        363   
 3 1938-01-01 France    Italy  Hungary      Braz… Sweden          84             15            18 375.700        376.  
 4 1950-01-01 Brazil    Urugu… Brazil       Swed… Spain           88             13            22 1.045.246        1.04
 5 1954-01-01 Switzerl… Germa… Hungary      Aust… Urugu…         140             16            26 768.607        769.  
 6 1958-01-01 Sweden    Brazil Sweden       Fran… Germa…         126             16            35 819.810        820.  
 7 1962-01-01 Chile     Brazil Czechoslova… Chile Yugos…          89             16            32 893.172        893.  
 8 1966-01-01 England   Engla… Germany FR   Port… Sovie…          89             16            32 1.563.135        1.56
 9 1970-01-01 Mexico    Brazil Italy        Germ… Urugu…          95             16            32 1.603.975        1.60
10 1974-01-01 Germany   Germa… Netherlands  Pola… Brazil          97             16            38 1.865.753        1.86
11 1978-01-01 Argentina Argen… Netherlands  Braz… Italy          102             16            38 1.545.791        1.54
12 1982-01-01 Spain     Italy  Germany FR   Pola… France         146             24            52 2.109.723        2.11
13 1986-01-01 Mexico    Argen… Germany FR   Fran… Belgi…         132             24            52 2.394.031        2.39
14 1990-01-01 Italy     Germa… Argentina    Italy Engla…         115             24            52 2.516.215        2.52
15 1994-01-01 USA       Brazil Italy        Swed… Bulga…         141             24            52 3.587.538        3.59
16 1998-01-01 France    France Brazil       Croa… Nethe…         171             32            64 2.785.100        2.78
17 2002-01-01 Korea/Ja… Brazil Germany      Turk… Korea…         161             32            64 2.705.197        2.70
18 2006-01-01 Germany   Italy  France       Germ… Portu…         147             32            64 3.359.439        3.36
19 2010-01-01 South Af… Spain  Netherlands  Germ… Urugu…         145             32            64 3.178.856        3.18
20 2014-01-01 Brazil    Germa… Argentina    Neth… Brazil         171             32            64 3.386.810        3.39
  

Al utilizarla entiende el punto como un decimal y cambia el tipo de dato a doble. Esto no es correcto ya que los valores presentados corresponden a cientos de miles y a millones. Podemos indicarle a la funcion que el separador de miles es el punto y el de decimales es la coma. Para eso usamos la funcion readr::parse_number y le pasamos los argumentos locale = locale(grouping_mark = ".", decimal_mark = ","):

  copas %>%
    mutate(asistencia = parse_number(Attendance, locale = locale(grouping_mark = "."))) %>% 
    select(Attendance, asistencia) 
    
# A tibble: 20 × 2
   Attendance asistencia
   <chr>           <dbl>
 1 590.549        590549
 2 363.000        363000
 3 375.700        375700
 4 1.045.246     1045246
 5 768.607        768607
 6 819.810        819810
 7 893.172        893172
 8 1.563.135     1563135
 9 1.603.975     1603975
10 1.865.753     1865753
11 1.545.791     1545791
12 2.109.723     2109723
13 2.394.031     2394031
14 2.516.215     2516215
15 3.587.538     3587538
16 2.785.100     2785100
17 2.705.197     2705197
18 3.359.439     3359439
19 3.178.856     3178856
20 3.386.810     3386810
> 

Ahora si, los datos estan en el formato correcto y podemos ordenarlos usando arrange.

copas %>% 
  mutate(asistencia = parse_number(Attendance, locale = locale(grouping_mark = "."))) %>% 
  arrange(desc(asistencia)) %>% 
  select(Year, Country, Attendance, asistencia)
 
 # A tibble: 20 × 4
   Year       Country      Attendance asistencia
   <date>     <chr>        <chr>           <dbl>
 1 1994-01-01 USA          3.587.538     3587538
 2 2014-01-01 Brazil       3.386.810     3386810
 3 2006-01-01 Germany      3.359.439     3359439
 4 2010-01-01 South Africa 3.178.856     3178856
 5 1998-01-01 France       2.785.100     2785100
 6 2002-01-01 Korea/Japan  2.705.197     2705197
 7 1990-01-01 Italy        2.516.215     2516215
 8 1986-01-01 Mexico       2.394.031     2394031
 9 1982-01-01 Spain        2.109.723     2109723
10 1974-01-01 Germany      1.865.753     1865753
11 1970-01-01 Mexico       1.603.975     1603975
12 1966-01-01 England      1.563.135     1563135
13 1978-01-01 Argentina    1.545.791     1545791
14 1950-01-01 Brazil       1.045.246     1045246
15 1962-01-01 Chile        893.172        893172
16 1958-01-01 Sweden       819.810        819810
17 1954-01-01 Switzerland  768.607        768607
18 1930-01-01 Uruguay      590.549        590549
19 1938-01-01 France       375.700        375700
20 1934-01-01 Italy        363.000        363000
>  

Otra forma de solucionar el mismo problema es remover los puntos y luego transformalo en numero con las funciones str_remove_all, que remueve los caracteres indicados en todas las ocurrencias que aparecen y as.numeric, que transforma al tipo numerico. Esta solucion aparece como una respuesta en StackOverflow y por eso la revisamos.

copas <- copas %>% 
 mutate(asistencia = as.numeric(str_remove_all(Attendance, fixed("."))))

Goleadores.

Para estas preguntas vamos a usar el conjunto de datos de jugadores. Hay una columna llamada Event con anotaciones al estilo “G20” o “Y56” que significan: “Gol a los 20 minutos” y “Tarjeta amarilla a los 56 minutos”, respectivamente. La columna puede tener ninguno (NA), uno o mas eventos por jugador. En el caso que tenga mas de un evento se separan con un espacio, como se muestra en la fila siete de la siguiente figura.

Para poder ordenar los jugadores por la cantidad de goles y saber quienes metieron goles en el segundo tiempo vamos a tener que poder contar los eventos “goles”. Para ello podemos separar los eventos en columnas diferentes o separarlos en filas diferentes.

Para este tipo de problema nos conviene separar los eventos en filas diferentes. Para eso vamos a usar la funcion separate_longer_delim del paquete tidyr. Esta funcion tiene como parametros la columna que queremos separar y el delimitador que vamos a usar. En este caso el delimitador es un espacio.


goleadores <- jugadores %>% 
  separate_longer_delim(Event, delim = " ")

Con este codigo obtenemos un conjunto de datos con una fila por cada evento y lo guardamos en el objeto goleadores, ahora la fila 7 se transformo en las filas 7 y 8 (dos filas), una con cada gol que hizo Andre Maschinot. Si chequeamos el conjunto de datos de jugadores tenia 37784 filas y ahora goleadores tiene xx filas.

Ordenar los jugadores por cantidad de goles

El conjunto de datos de goles, ahora tiene una fila para cada evento relacionado a un jugador. Entre esos eventos estan los goles, pero no son los unicos. Asi que primero tenemos que quedarnos solo con los goles. Para eso vamos a usar la funcion filter de dplyr y la funcion str_detect de stringr que nos permite buscar patrones en un texto.

goleadores %>% 
  filter(str_detect(Event,"G"))

Para ordenar los jugadores por cantidad de goles vamos a tener que contar cuantas veces aparece cada jugador en la columna Player Name. La primera solucion que Juan Cruz propuso fue usar group_by y summarise para contar cuantas veces aparece cada jugador y por ende cuantos goles hizo. Luego usamos arrange y desc para ordenar de mayor a menor.


goleadores %>% 
  filter(str_detect(Event,"G")) %>% 
  group_by(`Player Name`) %>% 
  summarise(goles = n()) %>% 
  arrange(desc(n))

# A tibble: 1,187 × 2
   `Player Name`                          n
   <chr>                              <int>
 1 KLOSE                                 17
 2 RONALDO                               16
 3 Gerd MUELLER                          13
 4 Just FONTAINE                         13
 5 PEL� (Edson Arantes do Nascimento)    12
 6 M�LLER                                11
 7 Sandor KOCSIS                         11
 8 Grzegorz LATO                         10
 9 Helmut RAHN                           10
10 JAIRZINHO                              9
# ℹ 1,177 more rows
# ℹ Use `print(n = ...)` to see more rows  

Vemos en el resultado problemas de encoding que intentaremos resolver en las proximas clases.

Charlamos de otra manera de realizar la misma consulta y la segunda solucion que propuso fue usar count que es una forma mas simple de hacer lo mismo.

goleadores %>% 
  filter(str_detect(Event,"G")) %>% 
  count(`Player Name`) %>% 
  arrange(desc(n))

Ejercicio 1: Sacar los 10 jugadores mas importantes y realizar un grafico de barras.

Usando los resultados de los goleadores, seleccionar los 10 jugadores que mas goles hicieron y hacer un grafico de barras.

Para resolver este ejercicio introducimos la funcion top_n que nos permite seleccionar los n elementos mas grandes de una columna.

goleadores %>% 
  filter(str_detect(Event,"G")) %>% 
  count(`Player Name`) %>% 
  arrange(desc(n)) %>% 
  top_n(10) 
  
  Selecting by n
# A tibble: 14 × 2
   `Player Name`                          n
   <chr>                              <int>
 1 KLOSE                                 17
 2 RONALDO                               16
 3 Gerd MUELLER                          13
 4 Just FONTAINE                         13
 5 PEL� (Edson Arantes do Nascimento)    12
 6 M�LLER                                11
 7 Sandor KOCSIS                         11
 8 Grzegorz LATO                         10
 9 Helmut RAHN                           10
10 JAIRZINHO                              9
11 Karl-Heinz RUMMENIGGE                  9
12 Paolo ROSSI                            9
13 Uwe SEELER                             9
14 VAVA                                   9

Al ver el resultado Juan Cruz pregunto porque si pedimos los 10 que mas goles metieron aparecen 14 resultados. La funcion top_n() va a devolver todos los casos que empaten en el puesto, asi que vemos 2 jugadores con 11 goles, 2 jugadores con 10 goles y 5 jugadores con 9 goles.

Ahora podemos usar ese resultado para realizar el grafico. Podemos extender el pipe y agregar la funcion ggplot para hacer el grafico de barras o bien podemos guardar el resultado en un objeto y luego hacer el grafico. Vamos por la segunda opcion.


Top10_gol <- goleadores %>% 
  filter(str_detect(Event,"G")) %>% 
  count(`Player Name`) %>% 
  arrange(desc(n)) %>% 
  top_n(10) 
  
Top10_gol  %>% 
  ggplot(aes(`Player Name`, n)) +
  geom_col() + 
  coord_flip()

En la proxima clase veremos en mas detalle como ggplot tabaja con capas y como podemos ir cambiando los elementos del grafico y como se ven.

Ejercicio 2: Jugadores que metieron goles en el segundo tiempo.

Este ejercicio queda como tarea para la proxima clase.