R You Ready

for interactive learning

flipbookr

https://github.com/EvaMaeRey/flipbookr
  • Evangeline Reynolds, Garrick Aden-Buie, and Emi Tanaka
  • adapted for quarto by Kieran Healy

learnr

https://rstudio.github.io/learnr/
  • Garrick Aden-Buie, Barret Schloerke, JJ Allaire, and Alexander Rossell Hayes

exams

https://www.r-exams.org/
  • Achim Zeileis, Nikolaus Umlauf, and Friedrich Leisch

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021)   #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es
# A tibble: 380 × 18
   league season match_id isResult home_id home_team home_abbr away_id away_team
   <chr>  <chr>  <chr>    <lgl>    <chr>   <chr>     <chr>     <chr>   <chr>    
 1 La_li… 2021/… 17136    TRUE     146     Valencia  VAL       142     Getafe   
 2 La_li… 2021/… 17138    TRUE     239     Mallorca  MAL       153     Real Bet…
 3 La_li… 2021/… 17139    TRUE     261     Cadiz     CAD       151     Levante  
 4 La_li… 2021/… 17137    TRUE     157     Osasuna   OSA       141     Espanyol 
 5 La_li… 2021/… 17140    TRUE     158     Alaves    ALA       150     Real Mad…
 6 La_li… 2021/… 17141    TRUE     152     Celta Vi… CEL       143     Atletico…
 7 La_li… 2021/… 17142    TRUE     148     Barcelona BAR       140     Real Soc…
 8 La_li… 2021/… 17143    TRUE     138     Sevilla   SEV       145     Rayo Val…
 9 La_li… 2021/… 17144    TRUE     154     Villarre… VIL       155     Granada  
10 La_li… 2021/… 17145    TRUE     207     Elche     ELC       147     Athletic…
# ℹ 370 more rows
# ℹ 9 more variables: away_abbr <chr>, home_goals <dbl>, away_goals <dbl>,
#   home_xG <dbl>, away_xG <dbl>, datetime <chr>, forecast_win <dbl>,
#   forecast_draw <dbl>, forecast_loss <dbl>

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022")
# A tibble: 198 × 18
   league season match_id isResult home_id home_team home_abbr away_id away_team
   <chr>  <chr>  <chr>    <lgl>    <chr>   <chr>     <chr>     <chr>   <chr>    
 1 La_li… 2021/… 17323    TRUE     142     Getafe    GET       150     Real Mad…
 2 La_li… 2021/… 17316    TRUE     207     Elche     ELC       155     Granada  
 3 La_li… 2021/… 17320    TRUE     143     Atletico… ATL       145     Rayo Val…
 4 La_li… 2021/… 17319    TRUE     158     Alaves    ALA       140     Real Soc…
 5 La_li… 2021/… 17321    TRUE     153     Real Bet… BET       152     Celta Vi…
 6 La_li… 2021/… 17322    TRUE     239     Mallorca  MAL       148     Barcelona
 7 La_li… 2021/… 17318    TRUE     154     Villarre… VIL       151     Levante  
 8 La_li… 2021/… 17325    TRUE     157     Osasuna   OSA       147     Athletic…
 9 La_li… 2021/… 17324    TRUE     261     Cadiz     CAD       138     Sevilla  
10 La_li… 2021/… 17329    TRUE     151     Levante   LEV       239     Mallorca 
# ℹ 188 more rows
# ℹ 9 more variables: away_abbr <chr>, home_goals <dbl>, away_goals <dbl>,
#   home_xG <dbl>, away_xG <dbl>, datetime <chr>, forecast_win <dbl>,
#   forecast_draw <dbl>, forecast_loss <dbl>

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG)
# A tibble: 198 × 6
   home_team       away_team      home_goals away_goals home_xG away_xG
   <chr>           <chr>               <dbl>      <dbl>   <dbl>   <dbl>
 1 Getafe          Real Madrid             1          0   0.900   0.913
 2 Elche           Granada                 0          0   1.45    0.966
 3 Atletico Madrid Rayo Vallecano          2          0   1.98    0.104
 4 Alaves          Real Sociedad           1          1   1.54    1.38 
 5 Real Betis      Celta Vigo              0          2   0.889   1.87 
 6 Mallorca        Barcelona               0          1   0.989   1.62 
 7 Villarreal      Levante                 5          0   4.19    0.423
 8 Osasuna         Athletic Club           1          3   0.522   2.49 
 9 Cadiz           Sevilla                 0          1   0.239   1.28 
10 Levante         Mallorca                2          0   1.32    1.17 
# ℹ 188 more rows

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team")
# A tibble: 396 × 6
   home_goals away_goals home_xG away_xG home      team           
        <dbl>      <dbl>   <dbl>   <dbl> <chr>     <chr>          
 1          1          0   0.900   0.913 home_team Getafe         
 2          1          0   0.900   0.913 away_team Real Madrid    
 3          0          0   1.45    0.966 home_team Elche          
 4          0          0   1.45    0.966 away_team Granada        
 5          2          0   1.98    0.104 home_team Atletico Madrid
 6          2          0   1.98    0.104 away_team Rayo Vallecano 
 7          1          1   1.54    1.38  home_team Alaves         
 8          1          1   1.54    1.38  away_team Real Sociedad  
 9          0          2   0.889   1.87  home_team Real Betis     
10          0          2   0.889   1.87  away_team Celta Vigo     
# ℹ 386 more rows

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG)
# A tibble: 396 × 6
   team            home      home_goals away_goals home_xG away_xG
   <chr>           <chr>          <dbl>      <dbl>   <dbl>   <dbl>
 1 Getafe          home_team          1          0   0.900   0.913
 2 Real Madrid     away_team          1          0   0.900   0.913
 3 Elche           home_team          0          0   1.45    0.966
 4 Granada         away_team          0          0   1.45    0.966
 5 Atletico Madrid home_team          2          0   1.98    0.104
 6 Rayo Vallecano  away_team          2          0   1.98    0.104
 7 Alaves          home_team          1          1   1.54    1.38 
 8 Real Sociedad   away_team          1          1   1.54    1.38 
 9 Real Betis      home_team          0          2   0.889   1.87 
10 Celta Vigo      away_team          0          2   0.889   1.87 
# ℹ 386 more rows

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG))
# A tibble: 396 × 7
   team            home      home_goals away_goals home_xG away_xG  excess
   <chr>           <chr>          <dbl>      <dbl>   <dbl>   <dbl>   <dbl>
 1 Getafe          home_team          1          0   0.900   0.913  0.100 
 2 Real Madrid     away_team          1          0   0.900   0.913 -0.913 
 3 Elche           home_team          0          0   1.45    0.966 -1.45  
 4 Granada         away_team          0          0   1.45    0.966 -0.966 
 5 Atletico Madrid home_team          2          0   1.98    0.104  0.0190
 6 Rayo Vallecano  away_team          2          0   1.98    0.104 -0.104 
 7 Alaves          home_team          1          1   1.54    1.38  -0.541 
 8 Real Sociedad   away_team          1          1   1.54    1.38  -0.381 
 9 Real Betis      home_team          0          2   0.889   1.87  -0.889 
10 Celta Vigo      away_team          0          2   0.889   1.87   0.128 
# ℹ 386 more rows

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team)
# A tibble: 396 × 7
# Groups:   team [20]
   team            home      home_goals away_goals home_xG away_xG  excess
   <chr>           <chr>          <dbl>      <dbl>   <dbl>   <dbl>   <dbl>
 1 Getafe          home_team          1          0   0.900   0.913  0.100 
 2 Real Madrid     away_team          1          0   0.900   0.913 -0.913 
 3 Elche           home_team          0          0   1.45    0.966 -1.45  
 4 Granada         away_team          0          0   1.45    0.966 -0.966 
 5 Atletico Madrid home_team          2          0   1.98    0.104  0.0190
 6 Rayo Vallecano  away_team          2          0   1.98    0.104 -0.104 
 7 Alaves          home_team          1          1   1.54    1.38  -0.541 
 8 Real Sociedad   away_team          1          1   1.54    1.38  -0.381 
 9 Real Betis      home_team          0          2   0.889   1.87  -0.889 
10 Celta Vigo      away_team          0          2   0.889   1.87   0.128 
# ℹ 386 more rows

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3))
# A tibble: 20 × 2
   team            excess
   <chr>            <dbl>
 1 Alaves          -0.244
 2 Athletic Club   -0.144
 3 Atletico Madrid  0.275
 4 Barcelona        0.107
 5 Cadiz           -0.185
 6 Celta Vigo      -0.048
 7 Elche            0.093
 8 Espanyol        -0.001
 9 Getafe           0.139
10 Granada         -0.092
11 Levante         -0.121
12 Mallorca        -0.159
13 Osasuna         -0.182
14 Rayo Vallecano  -0.476
15 Real Betis       0.067
16 Real Madrid     -0.301
17 Real Sociedad   -0.706
18 Sevilla          0.013
19 Valencia        -0.013
20 Villarreal      -0.132

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup()
# A tibble: 20 × 2
   team            excess
   <chr>            <dbl>
 1 Alaves          -0.244
 2 Athletic Club   -0.144
 3 Atletico Madrid  0.275
 4 Barcelona        0.107
 5 Cadiz           -0.185
 6 Celta Vigo      -0.048
 7 Elche            0.093
 8 Espanyol        -0.001
 9 Getafe           0.139
10 Granada         -0.092
11 Levante         -0.121
12 Mallorca        -0.159
13 Osasuna         -0.182
14 Rayo Vallecano  -0.476
15 Real Betis       0.067
16 Real Madrid     -0.301
17 Real Sociedad   -0.706
18 Sevilla          0.013
19 Valencia        -0.013
20 Villarreal      -0.132

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc())
# A tibble: 20 × 2
   team            excess
   <chr>            <dbl>
 1 Atletico Madrid  0.275
 2 Getafe           0.139
 3 Barcelona        0.107
 4 Elche            0.093
 5 Real Betis       0.067
 6 Sevilla          0.013
 7 Espanyol        -0.001
 8 Valencia        -0.013
 9 Celta Vigo      -0.048
10 Granada         -0.092
11 Levante         -0.121
12 Villarreal      -0.132
13 Athletic Club   -0.144
14 Mallorca        -0.159
15 Osasuna         -0.182
16 Cadiz           -0.185
17 Alaves          -0.244
18 Real Madrid     -0.301
19 Rayo Vallecano  -0.476
20 Real Sociedad   -0.706

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name))
# A tibble: 20 × 4
   team            excess season    url                                         
   <chr>            <dbl> <chr>     <chr>                                       
 1 Atletico Madrid  0.275 2022/2023 https://understat.com/team/Atletico_Madrid/…
 2 Getafe           0.139 2022/2023 https://understat.com/team/Getafe/2022      
 3 Barcelona        0.107 2022/2023 https://understat.com/team/Barcelona/2022   
 4 Elche            0.093 2022/2023 https://understat.com/team/Elche/2022       
 5 Real Betis       0.067 2022/2023 https://understat.com/team/Real_Betis/2022  
 6 Sevilla          0.013 2022/2023 https://understat.com/team/Sevilla/2022     
 7 Espanyol        -0.001 2022/2023 https://understat.com/team/Espanyol/2022    
 8 Valencia        -0.013 2022/2023 https://understat.com/team/Valencia/2022    
 9 Celta Vigo      -0.048 2022/2023 https://understat.com/team/Celta_Vigo/2022  
10 Granada         -0.092 <NA>      <NA>                                        
11 Levante         -0.121 <NA>      <NA>                                        
12 Villarreal      -0.132 2022/2023 https://understat.com/team/Villarreal/2022  
13 Athletic Club   -0.144 2022/2023 https://understat.com/team/Athletic_Club/20…
14 Mallorca        -0.159 2022/2023 https://understat.com/team/Mallorca/2022    
15 Osasuna         -0.182 2022/2023 https://understat.com/team/Osasuna/2022     
16 Cadiz           -0.185 2022/2023 https://understat.com/team/Cadiz/2022       
17 Alaves          -0.244 <NA>      <NA>                                        
18 Real Madrid     -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022 
19 Rayo Vallecano  -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/2…
20 Real Sociedad   -0.706 2022/2023 https://understat.com/team/Real_Sociedad/20…

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name)) |>
  drop_na()
# A tibble: 17 × 4
   team            excess season    url                                         
   <chr>            <dbl> <chr>     <chr>                                       
 1 Atletico Madrid  0.275 2022/2023 https://understat.com/team/Atletico_Madrid/…
 2 Getafe           0.139 2022/2023 https://understat.com/team/Getafe/2022      
 3 Barcelona        0.107 2022/2023 https://understat.com/team/Barcelona/2022   
 4 Elche            0.093 2022/2023 https://understat.com/team/Elche/2022       
 5 Real Betis       0.067 2022/2023 https://understat.com/team/Real_Betis/2022  
 6 Sevilla          0.013 2022/2023 https://understat.com/team/Sevilla/2022     
 7 Espanyol        -0.001 2022/2023 https://understat.com/team/Espanyol/2022    
 8 Valencia        -0.013 2022/2023 https://understat.com/team/Valencia/2022    
 9 Celta Vigo      -0.048 2022/2023 https://understat.com/team/Celta_Vigo/2022  
10 Villarreal      -0.132 2022/2023 https://understat.com/team/Villarreal/2022  
11 Athletic Club   -0.144 2022/2023 https://understat.com/team/Athletic_Club/20…
12 Mallorca        -0.159 2022/2023 https://understat.com/team/Mallorca/2022    
13 Osasuna         -0.182 2022/2023 https://understat.com/team/Osasuna/2022     
14 Cadiz           -0.185 2022/2023 https://understat.com/team/Cadiz/2022       
15 Real Madrid     -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022 
16 Rayo Vallecano  -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/2…
17 Real Sociedad   -0.706 2022/2023 https://understat.com/team/Real_Sociedad/20…

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name)) |>
  drop_na() |>
  slice(c(1:4, 15:17))
# A tibble: 7 × 4
  team            excess season    url                                          
  <chr>            <dbl> <chr>     <chr>                                        
1 Atletico Madrid  0.275 2022/2023 https://understat.com/team/Atletico_Madrid/2…
2 Getafe           0.139 2022/2023 https://understat.com/team/Getafe/2022       
3 Barcelona        0.107 2022/2023 https://understat.com/team/Barcelona/2022    
4 Elche            0.093 2022/2023 https://understat.com/team/Elche/2022        
5 Real Madrid     -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022  
6 Rayo Vallecano  -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/20…
7 Real Sociedad   -0.706 2022/2023 https://understat.com/team/Real_Sociedad/2022

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name)) |>
  drop_na() |>
  slice(c(1:4, 15:17)) |>
  gt()
team excess season url
Atletico Madrid 0.275 2022/2023 https://understat.com/team/Atletico_Madrid/2022
Getafe 0.139 2022/2023 https://understat.com/team/Getafe/2022
Barcelona 0.107 2022/2023 https://understat.com/team/Barcelona/2022
Elche 0.093 2022/2023 https://understat.com/team/Elche/2022
Real Madrid -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022
Rayo Vallecano -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/2022
Real Sociedad -0.706 2022/2023 https://understat.com/team/Real_Sociedad/2022

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name)) |>
  drop_na() |>
  slice(c(1:4, 15:17)) |>
  gt() |>
  cols_label(team = "Team",
             excess = "Goal Excess",
             season = "Season",
             url = "Club Website")
Team Goal Excess Season Club Website
Atletico Madrid 0.275 2022/2023 https://understat.com/team/Atletico_Madrid/2022
Getafe 0.139 2022/2023 https://understat.com/team/Getafe/2022
Barcelona 0.107 2022/2023 https://understat.com/team/Barcelona/2022
Elche 0.093 2022/2023 https://understat.com/team/Elche/2022
Real Madrid -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022
Rayo Vallecano -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/2022
Real Sociedad -0.706 2022/2023 https://understat.com/team/Real_Sociedad/2022

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name)) |>
  drop_na() |>
  slice(c(1:4, 15:17)) |>
  gt() |>
  cols_label(team = "Team",
             excess = "Goal Excess",
             season = "Season",
             url = "Club Website") |>
  cols_align(align = "center")
Team Goal Excess Season Club Website
Atletico Madrid 0.275 2022/2023 https://understat.com/team/Atletico_Madrid/2022
Getafe 0.139 2022/2023 https://understat.com/team/Getafe/2022
Barcelona 0.107 2022/2023 https://understat.com/team/Barcelona/2022
Elche 0.093 2022/2023 https://understat.com/team/Elche/2022
Real Madrid -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022
Rayo Vallecano -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/2022
Real Sociedad -0.706 2022/2023 https://understat.com/team/Real_Sociedad/2022

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name)) |>
  drop_na() |>
  slice(c(1:4, 15:17)) |>
  gt() |>
  cols_label(team = "Team",
             excess = "Goal Excess",
             season = "Season",
             url = "Club Website") |>
  cols_align(align = "center") |>
  tab_options(column_labels.background.color = "cornflowerblue",
              table.font.names = "Caveat",
              table.font.style = "oblique",
              table.font.size = 24,
              column_labels.font.weight = "bold",
              column_labels.vlines.width = 2,
              column_labels.vlines.color = "darkblue",
              column_labels.vlines.style = "solid",
              table_body.vlines.width = 2,
              table_body.hlines.width = 2,
              table_body.vlines.color = "darkblue",
              table_body.vlines.style = "solid"
  )
Team Goal Excess Season Club Website
Atletico Madrid 0.275 2022/2023 https://understat.com/team/Atletico_Madrid/2022
Getafe 0.139 2022/2023 https://understat.com/team/Getafe/2022
Barcelona 0.107 2022/2023 https://understat.com/team/Barcelona/2022
Elche 0.093 2022/2023 https://understat.com/team/Elche/2022
Real Madrid -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022
Rayo Vallecano -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/2022
Real Sociedad -0.706 2022/2023 https://understat.com/team/Real_Sociedad/2022

flipbookr Runthrough

#es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |  #es <- understat_league_match_results(league = "La liga", season_start_year = 2021) |> as_tibble
es |>
  filter(year(datetime) == "2022") |>
  select(home_team, away_team, home_goals, away_goals, home_xG, away_xG) |>
  pivot_longer(-c(home_goals, away_goals, home_xG, away_xG), names_to = "home", values_to = "team") |>
  select(team, home, home_goals, away_goals, home_xG, away_xG) |>
  mutate(excess = ifelse(home == "home_team", home_goals - home_xG, away_goals - away_xG)) |>
  group_by(team) |>
  summarise(excess = mean(excess) |> round(3)) |>
  ungroup() |>
  arrange(excess |> desc()) |>
  left_join(teams_meta, by = join_by(team == team_name)) |>
  drop_na() |>
  slice(c(1:4, 15:17)) |>
  gt() |>
  cols_label(team = "Team",
             excess = "Goal Excess",
             season = "Season",
             url = "Club Website") |>
  cols_align(align = "center") |>
  tab_options(column_labels.background.color = "cornflowerblue",
              table.font.names = "Caveat",
              table.font.style = "oblique",
              table.font.size = 24,
              column_labels.font.weight = "bold",
              column_labels.vlines.width = 2,
              column_labels.vlines.color = "darkblue",
              column_labels.vlines.style = "solid",
              table_body.vlines.width = 2,
              table_body.hlines.width = 2,
              table_body.vlines.color = "darkblue",
              table_body.vlines.style = "solid"
  )
Team Goal Excess Season Club Website
Atletico Madrid 0.275 2022/2023 https://understat.com/team/Atletico_Madrid/2022
Getafe 0.139 2022/2023 https://understat.com/team/Getafe/2022
Barcelona 0.107 2022/2023 https://understat.com/team/Barcelona/2022
Elche 0.093 2022/2023 https://understat.com/team/Elche/2022
Real Madrid -0.301 2022/2023 https://understat.com/team/Real_Madrid/2022
Rayo Vallecano -0.476 2022/2023 https://understat.com/team/Rayo_Vallecano/2022
Real Sociedad -0.706 2022/2023 https://understat.com/team/Real_Sociedad/2022

flipbookr Runthrough

ggplot()

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff")

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff") +
geom_sf(data=world_sf |> st_transform(crs="+proj=moll"),
aes(fill = NAME), show.legend = FALSE)

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff") +
geom_sf(data=world_sf |> st_transform(crs="+proj=moll"),
aes(fill = NAME), show.legend = FALSE) +
scale_fill_manual(values = rep(paletteer_d("MexBrewer::Naturaleza", n=7), 35))

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff") +
geom_sf(data=world_sf |> st_transform(crs="+proj=moll"),
aes(fill = NAME), show.legend = FALSE) +
scale_fill_manual(values = rep(paletteer_d("MexBrewer::Naturaleza", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("palettetown::crobat", n=7), 35))

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff") +
geom_sf(data=world_sf |> st_transform(crs="+proj=moll"),
aes(fill = NAME), show.legend = FALSE) +
scale_fill_manual(values = rep(paletteer_d("MexBrewer::Naturaleza", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("palettetown::crobat", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("lisa::JosefAlbers", n=5), 50))

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff") +
geom_sf(data=world_sf |> st_transform(crs="+proj=moll"),
aes(fill = NAME), show.legend = FALSE) +
scale_fill_manual(values = rep(paletteer_d("MexBrewer::Naturaleza", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("palettetown::crobat", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("lisa::JosefAlbers", n=5), 50)) +
scale_fill_manual(values = rep(my_cols, 35))

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff") +
geom_sf(data=world_sf |> st_transform(crs="+proj=moll"),
aes(fill = NAME), show.legend = FALSE) +
scale_fill_manual(values = rep(paletteer_d("MexBrewer::Naturaleza", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("palettetown::crobat", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("lisa::JosefAlbers", n=5), 50)) +
scale_fill_manual(values = rep(my_cols, 35)) +
theme_void()

flipbookr Runthrough

ggplot() +
geom_sf(data=oceans_moll.sf, fill="#cce6ff") +
geom_sf(data=world_sf |> st_transform(crs="+proj=moll"),
aes(fill = NAME), show.legend = FALSE) +
scale_fill_manual(values = rep(paletteer_d("MexBrewer::Naturaleza", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("palettetown::crobat", n=7), 35)) +
scale_fill_manual(values = rep(paletteer_d("lisa::JosefAlbers", n=5), 50)) +
scale_fill_manual(values = rep(my_cols, 35)) +
theme_void()

Advantages of flipbookr

  • follows philosophy of tidyverse and ggplot

  • empasises use of the pipe, |>

  • good coding practice

    • every line does one job and one job only

Limitations of flipbookr

  • really only useful for coding

  • the #ROTATE option is a little picky

  • careful not to use it too much

Mechanics of flipbookr

  • install.package("flipbookr")

    • works in rmarkdown
  • remotes::install_github("kjhealy/flipbookr@quarto")

  • make an r chunk of your code with options:

    • #| label: my_chunk_name
    • #| echo: false
    • #| eval: false
  • below this, have inline r code using chunq_reveal(chunk_name = "my_chunk_name")

    • automatically gives two-column side-by-side format
  • can set how lines are revealed

    • normally does it line by line (break_type = "auto")
    • #BREAK to specify where to stop
    • #ROTATE to cycle between lines of code

learnr

Advantages of learnr

  • typically take a quiz after 20 & 40 minutes of lecture

    • do this every time, students like the rhythm
  • can do any topic, not just computing

  • giving hints is very useful

Disadvantages

  • can’t build randomness into questions

  • I can’t see feedback/answers from students

  • is a bit flaky with quarto-style chunks

  • need to publish on a shinyapps server

Mechanics of learnr

  • 3 step process

    1. create a quarto document to make a shiny app

    2. upload this on to a server such as shinyapps.io

    3. incorporate this within lecture slides

1. Making learnr app

  • make a quarto document with the following yaml
    ---
    title: "My Exciting learnr Quiz"
    output: learnr::tutorial
    runtime: shiny_prerendered
    execute:
      echo: false
      warning: false
      message: false
    ---
  • include a blank coding space with a code chunk headed like this:
    {r quiz_question, exercise=TRUE, exercise.eval = TRUE}
    
  • include a hint with a code chunk headed like this:
    {r quiz_question-hint-1}
    
  • can add MCQ’s and checkbox quizzes using quiz() and question()
quiz(
  question("What is the capital city of France?",
    answer("Berlin"),
    answer("Bordeaux"),
    answer("Paris", correct = TRUE),
    answer("Rome")
  ),
  question("Which of the following are volcanoes?",
    answer("Kilamanjaro", correct = TRUE),
    answer("Everest"),
    answer("Etna", correct = TRUE),
    answer("Rainier", correct = TRUE)
  )
)

2. Upload to a shiny server

3. Add to lecture

  • Add code chunk with:
    xaringanExtra::embed_xaringan(url = "https://eugene-hickey.shinyapps.io/my-learnr-example/", ratio = "16:9")
    

exams

Advantages of exams

  • part of academic hosting platform (moodle, blackboard, canvas, etc)

  • weekly ten question quiz

    • get three attempts
    • done in students time
    • they get instant feedback
  • works for all subject matter

  • can build in randomisation

  • get marks back to lecturer

Disadvantages of exams

  • works best for moodle, not sure how good with other VLE’s

  • interactivity is tricky

  • less production ready than other tools

Mechanics of exams

  • 6 step process

    1. Generate data and solutions

    2. Create question text for student

    3. Create student feedback

    4. Generate meta-information

    5. Use exams package to make moodle-xml

    6. Upload this xml to moodle

  • best to start with r exams templates

1. Generate Data

{r data generation, echo = FALSE, results = "hide", 
message=FALSE, warning=FALSE}
library(tidyverse)
library(exams)
library(gt)
set.seed(42)
ok <- FALSE
while(!ok){
  x1 <- sample(1:20, 3)
  x2 <- sample(1:20, 3)
  my_soln <- x1 * x2
  ok <- !(sum(duplicated(my_soln)))
}
my_table <- tibble(
  x1 = x1, x2 = x2, 
  my_answers = c("##ANSWER1##", "##ANSWER2##", "##ANSWER3##")
  )
  • note, .Rmd file with no yamlheader.

2. Question Text

Question
========
In the table below, multiply _Value 1_ by _Value 2_ 
and type the answer in _Result_:

my_table |> 
  gt() |>  
  cols_label(x1 = "Value 1",
             x2 = "Value 2",
             my_answers = "Result")

3. Feedback

Solution
========
Use "Value 1" $\times$ "Value 2" to get result. 
The answers should be `r my_soln`.

4. Meta-Information

Meta-information
================
extype: cloze
exsolution: `r paste(my_soln, collapse = "|")`
exclozetype: num|num|num
exname: exams_example
extol: 0.05
exextra[numwidth,logical]: TRUE

5. Make Moodle XML

exams2moodle(file = "exams-example.Rmd", n = 100)
  • this will make a file called moodlequiz.xml with 100 exemplars of the quiz with different input values.

6. Upload to moodle

Thank you!

{{< fa solid blog >}} www.fizzics.ie/
{{< fa brands orcid >}} 0000-0001-9813-9323
{{< fa brands mastodon >}} @eugene100hickey
{{< fa brands twitter >}} @eugene100hickey
{{< fa brands github >}} eugene100hickey.github.io/
Figure 1

Summary

  • R has some great packages for teaching

  • we looked at three here:

    • flipbookr for walking through code chunks

    • learnr for producing little test questions in the middle of a lecture

    • exams for producing assessments to be run online