Activité 2 - Manipulations et graphiques

Chargez les données

df <- "https://lbelzile.github.io/multi/files/data/MarathonBerlin2022.csv"
marathon <- read.csv(df, header = TRUE)

Manipulations

  1. Transformez les types de variables (temps, facteurs, entiers)
  2. Obtenez les noms associés aux codes des pays (codes du CIO)
  3. Transformez en valeurs manquantes
    • les valeurs de sexe non déclarées
    • les classements des personnes qui n’ont pas complété la course, ou qui ont été disqualifiées
  4. Retirez les variables starttime, grosstime et division
  5. Créez un facteur vague représentant le temps de la vague de départ (starttime)

Graphiques

  1. Créez un diagramme à bande du nombre de participants par pays (10 premiers)
  2. Tracez un histogramme des temps de complétion du marathon en fonction du sexe de l’athlète
  3. Créez un diagramme spaghetti (ligne brisée) de la vitesse des 25 coureurs les plus rapides en fonction de la distance par intervalle de 5km (difficile).

Réponses

# Est-ce que les classements par genre sont uniques?
head(sort(table(marathon$position_gender), decreasing = TRUE))

    –   DSQ 11187  9840 10057 10094 
  727    53     5     5     4     4 
# Réponse: DSQ pour disqualifiés, - pour manquants, plusieurs doublons
# Est-ce que le classement global est unique?
head(sort(table(marathon$position), decreasing = TRUE))

  DNF     1    10   100  1000 10000 
  727     1     1     1     1     1 
# Oui, mais 727 DNF (pas complété).
library(dplyr, warn.conflicts = FALSE)
library(tidyr)
library(lubridate, warn.conflicts = FALSE)
library(countrycode)

berlin <- marathon |>
  mutate( # transformer les variables
    position = as.integer(
      na_if(position, "DNF")
    ),
    position_gender = as.integer(
      replace_values(position_gender, c("–", "DSQ") ~ NA)
    ),
    countrycode = case_when(nchar(country) == 3L ~ country, .default = NA),
    country = recode_values(
      countrycode,
      from = countrycode::codelist$ioc,
      to = countrycode::codelist$country.name.fr,
      default = NA
    ),
    sex = factor(na_if(sex, "-")),
    bib = factor(bib),
    category = factor(category),
    vague = factor(substr(start_raw_time, 1, 5)),
    half = na_if(half, "")
  ) |>
  mutate(
    start_raw_time = hms(na_if(start_raw_time, "–"), quiet = TRUE),
    across(half:nettime, ~ as.duration(hms(na_if(.x, "–"), quiet = TRUE))),
  ) |>
  # retirer les variables
  select(
    !c(
      division, # pas utilisée
      grosstime, # information déjà avec nettime
      starttime # transformé en facteur (vague)
    )
  )
# Graphique 1: Diagramme à bande des 10 pays principaux (nombre de coureurs)
library(ggplot2)
theme_set(theme_classic())
library(tinyplot)
tinytheme("clean2")
# Facteur, avec ordre par nombre
pays10 <- as.data.frame(
  sort(with(berlin, table(country)), decreasing = TRUE)[10:1]
) |>
  mutate(country = factor(country, levels = country, labels = country))

ggplot(
  data = pays10,
  mapping = aes(
    y = country,
    x = Freq
  )
) +
  geom_col() +
  scale_x_continuous(limits = c(0, NA), expand = expansion()) +
  labs(
    y = "", x = "",
    title = "nombre de participants par pays",
    caption = "Marathon de Berlin (2022)"
  )

plt(
  Freq ~ country,
  data = pays10,
  type = "barplot",
  main = "Nombre de participants par pays",
  xlab = "",
  ylab = "",
  flip = TRUE,
  cap = "Source: Marathon de Berlin, 2022"
)

# Graphique 2: vitesse par sexe

ggplot(
    data = berlin |> 
      drop_na(sex) |> 
      mutate(sex = factor(
        sex, 
        levels = c("F","M"), 
        labels = c("femmes","hommes"))),
    mapping = aes(
        x = nettime / 3600,
        fill = sex,
    )
) +
    geom_histogram(bins = 30, alpha = 0.5) +
    viridis::scale_fill_viridis(discrete = TRUE) +
    scale_y_continuous(limits = c(0, NA), expand = expansion()) +
    labs(fill = "sexe",
        y = "décompte",
        x = "temps de complétion du marathon (en heures)",
        caption = "Marathon de Berlin (2022)"
    ) + 
    theme(legend.position = c(0.9,0.9))

plt(
  ~ I(as.numeric(nettime) / 3600)  | sex,
  data = berlin |> 
    filter(!is.na(sex)) |> 
    mutate(sex = factor(
      sex, 
      levels = c("F","M"), 
      exclude = NA, 
      labels = c("femmes","hommes"))),
  type = "histogram",
  main = "temps de complétion du marathon (en heures)",
  xlab = "",
  legend = list("topright", title = "sexe"),
  ylab = "décompte",
  cap = "Source: Marathon de Berlin, 2022"
)

# Graphique 3: vitesses de passage du top 25

# Transformer les temps de passage en vitesse
berlin <- berlin |>
  mutate(
    V5 = 5 / as.numeric(X5k) * 3600,
    V10 = 5 / as.numeric(X10k - X5k) * 3600,
    V15 = 5 / as.numeric(X15k - X10k) * 3600,
    V20 = 5 / as.numeric(X20k - X15k) * 3600,
    V25 = 5 / as.numeric(X25k - X20k) * 3600,
    V30 = 5 / as.numeric(X30k - X25k) * 3600,
    V35 = 5 / as.numeric(X35k - X30k) * 3600,
    V40 = 5 / as.numeric(X40k - X35k) * 3600,
    Vmoy = 42.195 / as.numeric(nettime) * 3600,
  ) |>
  mutate(across(starts_with("V", ignore.case = FALSE),
                \(x) round(x, digits = 2)))

top25 <- berlin |>
  select(position, starts_with("V", ignore.case = FALSE)) |>
  select(!Vmoy) |>
  filter(position <= 25) |>
  tidyr::pivot_longer(
    cols = tidyr::starts_with("V"),
    names_to = "km",
    names_prefix = "V",
    values_to = "speed"
  ) |>
  mutate(km = as.numeric(km))

plt(
  x = speed ~ km | position,
  type = "b",
  xlab = "km",
  ylab = "",
  main = "Performance des 25 meilleurs coureurs",
  sub = "Vitesse (km/h) par segment de 5km",
  cap = "Source: Marathon de Berlin, 2022",
  data = top25,
  legend = FALSE
)

ggplot(
  data = top25,
  mapping = aes(
    x = km,
    group = factor(position),
    col = factor(position),
    y = speed
  )
) +
  geom_point(show.legend = FALSE) +
  geom_line(show.legend = FALSE) +
  labs(
    x = "km",
    y = "",
    #     col = "rang",
    subtitle = "Vitesse (km/h) par segment de 5km",
    title = "Performance des 25 meilleurs coureurs",
    caption = "Source: Marathon de Berlin, 2022",
  )