# Quick and dirty analysis of 10mila 2019 results

data analysis
Tekijä

Markus Kainu

Julkaistu

28. huhtikuuta 2019

A Swedish spring classic in orienteering 10mila was raced this weeked in Östra Göinge in Skåne. Similar to last two years, IFK Göteborg won the mens 10 leg overnight relay. I took a little stab at their results system at online.10mila.se/, pulled out the data and did two graphs. You can download the excel data with two sheets from here: 10mila leg times & split times. I included the source code in R in case someone is interested in it.

Here are the positions for top 10 teams at each exchange!

And below a very tall image with positions at each split point at each leg.

## Source code

Is below.

</>
``````library(httr)
library(rvest)
library(dplyr)
osuus <- 10
looptbl <- data_frame(
leg = 1:10,
splits = list(list(1,2,3,4,5), # 1
list(1,2,3,4,5), # 2
list(1,2,3), # 3
list(1,2,3,4,5), # 4
list(1,2,3,4), # 5
list(1,2,3,4), # 6
list(1,2,3), # 7
list(1,2,3,4,5), # 8
list(1,2), # 9
list(1,2,3,4,5,6)) # 10
)

if (!file.exists("./data/osuusdata19.RDS")){
# **********************************************************
# vaihtoajat
d_leg <- data_frame()
for (leg in 1:osuus){
# for (leg in 1:10){
html_table(fill = TRUE) %>%
.[[5]] %>%
.[-1:-2,] %>%
as_tibble() -> tmp
names(tmp) <- c("place","name","club","time","diff")
tmp\$leg <- leg
d_leg <- bind_rows(d_leg,tmp)
}
d_leg %>%
mutate(
min = as.integer(sub(":.+\$", "", time)),
s   = as.integer(sub("^.+:", "", time)),
secs = min * 60 + s,
diff_min = as.integer(sub(":.+\$", "", diff)),
diff_s   = as.integer(sub("^.+:", "", diff)),
diff_secs = diff_min * 60 + diff_s
) -> d_leg2
saveRDS(d_leg2, "./data/osuusdata19.RDS")
}

leg_info <- data_frame(leg = 1:10)
leg_info %>%
mutate(length = case_when(
leg == 1 ~ 12.0,
leg == 2 ~ 11.6,
leg == 3 ~ 6.1,
leg == 4 ~ 17.8,
leg == 5 ~ 11.0,
leg == 6 ~ 10.1,
leg == 7 ~ 8.6,
leg == 8 ~ 12.0,
leg == 9 ~ 5.2,
leg == 10 ~ 14.0
),
length_cum = cumsum(length)) -> leg_info

d_leg22 <- left_join(d_leg2,leg_info)

d_leg_0 <- d_leg22 %>%
filter(leg == osuus) %>%
mutate(length_cum = 0,
diff_secs = 0,
leg = 0)
d_leg_11 <- bind_rows(d_leg_0,
d_leg22)

all_legs <- d_leg_11 # for excel

top10 <- d_leg2 %>% filter(leg == osuus) %>%
slice(1:10) %>%
pull(club)
d_leg_111 <- d_leg_11 %>% filter(club %in% top10)

ipsum_palette <- c("#d18975", "#8fd175", "#3f2d54", "#75b8d1", "#2d543d", "#c9d175", "#d1ab75", "#d175b8", "#758bd1")
ipsum_palette <- c(ipsum_palette,ipsum_palette,ipsum_palette)

library(ggplot2)
library(hrbrthemes)
library(viridis)
ggplot(d_leg_111, aes(x = length_cum, y = diff_secs/60, color = club, fill = club)) +
geom_line(alpha = .8) + geom_point(shape = 21, color = "white", alpha = .8, size = 4) +
# scale_x_continuous(breaks = leg_info\$length_cum , labels = leg_info\$leg) +
scale_y_reverse() +
geom_text(aes(label = place), color = "white", family = "Roboto Condensed", size = 2.5, fontface= "bold") +
theme_ipsum_rc() +
ggrepel::geom_text_repel(data = d_leg_111 %>% filter(leg == max(leg)), aes(label = club), nudge_y = -.2, size = 2.7, family = "Roboto Condensed") +
theme(legend.position = "none") +
# scale_fill_ipsum() + scale_color_ipsum() +
scale_fill_manual(values = c(rev(ipsum_palette),"black")) + scale_color_manual(values = c(rev(ipsum_palette),"black")) +
labs(title = "Top ten teams in 10mila 2019",
subtitle = "Time difference to lead in each exchange",
caption = paste0("Data: online.10mila.se\n",Sys.time()),
x = "distance (km)", y = "minutes behind the lead") -> plot
plot

# **********************************************************
# väliajat

d_splits <- data_frame()
for (leg in 1:osuus){
# for (leg in 1:10){
splits <- unlist(looptbl\$splits[leg])
split_dat <- data_frame()
for (split1 in splits){
html_table(fill = TRUE) %>%
.[[5]] %>%
.[-1:-2,] %>%
as_tibble() -> tmp
names(tmp) <- c("place","name","club","time","diff")
tmp\$leg <- leg
tmp\$split1 <- split1
split_dat <- bind_rows(split_dat,tmp)
}
d_splits <- bind_rows(d_splits,split_dat)
}
d_splits %>%
mutate(
min = as.integer(sub(":.+\$", "", time)),
s   = as.integer(sub("^.+:", "", time)),
secs = min * 60 + s,
diff_min = as.integer(sub(":.+\$", "", diff)),
diff_s   = as.integer(sub("^.+:", "", diff)),
diff_secs = diff_min * 60 + diff_s
) -> d_splits2
}

split_info <- d_splits2 %>% count(leg,split1) %>% select(-n)
split_info %>%
mutate(length = case_when(
leg == 1 & split1 ==  1 ~ 2.7,
leg == 1 & split1 ==  2 ~ 5.3,
leg == 1 & split1 ==  3 ~ 8.7,
leg == 1 & split1 ==  4 ~ 10.1,
leg == 1 & split1 ==  5 ~ 11.6,

leg == 2 & split1 == 1 ~ 2.5,
leg == 2 & split1 == 2 ~ 5.1,
leg == 2 & split1 == 3 ~ 8.3,
leg == 2 & split1 == 4 ~ 9.7,
leg == 2 & split1 == 5 ~ 11.2,

leg == 3 & split1 == 1 ~ 2.5,
leg == 3 & split1 == 2 ~ 4.2,
leg == 3 & split1 == 3 ~ 5.7,

leg == 4 & split1 == 1 ~ 2.2,
leg == 4 & split1 == 2 ~ 8.5,
leg == 4 & split1 == 3 ~ 12.5,
leg == 4 & split1 == 4 ~ 15,
leg == 4 & split1 == 5 ~ 17.2,

leg == 5 & split1 == 1 ~ 3.1,
leg == 5 & split1 == 2 ~ 4.8,
leg == 5 & split1 == 3 ~ 7.7,
leg == 5 & split1 == 4 ~ 10.6,

leg == 6 & split1 == 1 ~ 3.1,
leg == 6 & split1 == 2 ~ 4.8,
leg == 6 & split1 == 3 ~ 6.8,
leg == 6 & split1 == 4 ~ 9.7,

leg == 7 & split1 == 1 ~ 2.9,
leg == 7 & split1 == 2 ~ 5.3,
leg == 7 & split1 == 3 ~ 8.2,

leg == 8 & split1 == 1 ~ 2.8,
leg == 8 & split1 == 2 ~ 6.1,
leg == 8 & split1 == 3 ~ 8.3,
leg == 8 & split1 == 4 ~ 10.2,
leg == 8 & split1 == 5 ~ 11.6,

leg == 9 & split1 == 1 ~ 3.4,
leg == 9 & split1 == 2 ~ 4.8,

leg == 10 & split1 == 1 ~ 2.8,
leg == 10 & split1 == 2 ~ 5.7,
leg == 10 & split1 == 3 ~ 8.2,
leg == 10 & split1 == 4 ~ 10.5,
leg == 10 & split1 == 5 ~ 12.3,
leg == 10 & split1 == 6 ~ 13.6

)) %>%
group_by(leg) %>%
mutate(length_cum = cumsum(length)) -> split_info

d_splits_10 <- left_join(d_splits2,split_info)

d_leg0 <- all_legs %>%
filter(leg %in% 1:osuus) %>%
mutate(length = 0,
diff_secs = 0,
leg = 1)
if (exists("d_leg_10")){
d_leg_11 <- bind_rows(all_legs,
d_leg_10)
} else {
d_leg_11 <- all_legs
}

d_leg_11_0 <- d_leg_11 %>%
mutate(length = 0, leg = leg + 1)

legdata <- bind_rows(d_leg_11,d_leg_11_0)

d_splits_10 <- bind_rows(d_splits_10,legdata)

d_splits_10 <- d_splits_10 %>% filter(leg != 0, leg != 11)

d_splits_10\$leg2 <- paste0("Leg ", d_splits_10\$leg)
d_splits_10\$leg2 <- factor(d_splits_10\$leg2, levels = c("Leg 1","Leg 2","Leg 3","Leg 4","Leg 5","Leg 6","Leg 7","Leg 8","Leg 9","Leg 10"))

all_splits <- d_splits_10 # exceliin

d_splits_10 <- d_splits_10 %>% filter(club %in% top10)

library(ggplot2)
library(hrbrthemes)
library(viridis)
d_splits_10 <- d_splits_10 %>% filter(leg %in% 1:osuus)

ggplot(d_splits_10, aes(x = length,
y = diff_secs/60,
# y = diff_secs,
color = club,
fill = club)) +
geom_line(alpha = .8) + geom_point(shape = 21, color = "white", alpha = .8, size = 4) +
ggrepel::geom_text_repel(data = d_splits_10 %>%
group_by(leg2) %>%
filter(length == max(length)),
aes(label = paste0(name,"\n",club)),
nudge_y = -.2,
nudge_x = 1,
size = 2.6,
lineheight = .8,
family = "Roboto Condensed") +
facet_wrap(~leg2, ncol = 1, scales = "free") +
# scale_x_continuous(breaks = 0:18, labels = 0:18, limits = c(0,18)) +
scale_x_continuous(breaks = 0:19, labels = 0:19, limits = c(0,19)) +
scale_y_reverse() +
geom_text(aes(label = place), color = "white", family = "Roboto Condensed", size = 2.5, fontface= "bold") +
theme_ipsum_rc() +
theme(legend.position = "none") +
scale_fill_manual(values = c(rev(ipsum_palette),"black")) + scale_color_manual(values = c(rev(ipsum_palette),"black")) +
# theme(plot.margin = unit(0,0,0,0)) +
# theme(margin(t = 0, r = 0, b = 0, l = 0, unit = "pt")) +
labs(title = glue::glue("Top 20 teams in 10mila 2019 in legs 1-{osuus}"),
subtitle = "Time difference to lead in each split",
caption = paste0("Data: online.10mila.se\n",Sys.time()),
x = "distance from exchange (km)", y = "minutes behind the lead") -> splitspic``````

CC BY 4.0

## Viittaus

BibTeX-viittaus:
``````@online{kainu,
author = {Markus Kainu and Markus Kainu},
title = {Quick and dirty analysis of 10mila 2019 results},
date = {},
url = {https://markuskainu.fi/posts/2019-04-28-10-mila-ostra-goinge},
langid = {fi}
}
``````
Viitatkaa tähän teokseen seuraavasti:
Markus Kainu, and Markus Kainu. n.d. “Quick and dirty analysis of 10mila 2019 results.” https://markuskainu.fi/posts/2019-04-28-10-mila-ostra-goinge.