6 min read

Show me what you got

Alright, let’s see what we can do here. Too much iris could be boring, so I thought I’d contribute some data by myself. Since my fitbit stopped working early this year, I’ve switched back to my old Garmin forerunner 10, and it turns out that you can downlowd .csv file of previous activities through Garmin connect. Now that’s pretty cool - I’ll just use this data.

The data

library(tidyverse)
library(lubridate)
library(plotly)
input_df <- read_csv("../../static/data/Activities.csv",
                     na=c("--"),
                     col_types=list(
                       Time=col_character(),
                       `Avg Pace`=col_character(),
                       `Best Pace`=col_character()))

This is a shabby Forerunner 10 so I don’t get all those fancy metrics such as heart rate and stride. So I’ll remove those useless empty columns. As always, date / time is a mess, so I’ll also manually clean up the duration and pace columns. Let’s see if DT works after cleaning up the data.

df <- input_df[c("Date", "Title", "Distance", "Time", "Avg Pace", "Best Pace", "Elev Gain", "Elev Loss")] %>%
  # Time is the duration of runs. Make it numeric and rename to Duration
  separate(Time, c("H", "M", "S"), sep=":", fill="left") %>%
  replace_na(list(H="0", M="0", S="0")) %>%
  mutate(Duration=as.numeric(H) + as.numeric(M) / 60 + as.numeric(S) / 3600) %>%
  select(-c(H, M, S)) %>%
  # Avg Pace should use unit minute
  separate(`Avg Pace`, c("M", "S"), sep=":", fill="left") %>%
  replace_na(list(M="0", S="0")) %>%
  mutate(`Avg Pace`=as.numeric(M) + as.numeric(S) / 60) %>%
  select(-c(M, S)) %>%
  # Best Pace should also use unit minute
  separate(`Best Pace`, c("M", "S"), sep=":", fill="left") %>%
  replace_na(list(M="0", S="0")) %>%
  mutate(`Best Pace`=as.numeric(M) + as.numeric(S) / 60) %>%
  select(-c(M, S)) %>%
  filter(Distance > 0)

# there's this one time I forgot to turn the watch off, and it ended up giving rediculous duration. Remove...
df <- df[df$Date != as_datetime("2017-07-26 08:29:41 UTC"), ]

# Title contains location, parse it out
df <- df %>%
  mutate(Location=gsub(" Running", "", Title)) %>%
  mutate(Location=ifelse(.$Location == "Untitled", "Durham", .$Location))

# That's pretty much all the cleaning.
DT::datatable(df, options = list(pageLength = 5, scrollX = TRUE))

Make some plots

Has my distance improved? Looks like so.

ggplot(df, aes(Date, Distance)) +
  geom_point(aes(color=Location), alpha=0.8) +
  theme_light()

Has my pace improved? Not very obvious. Anyways I just want to see if plotly works, so let’s add some text labels.

p <- ggplot(df, aes(Date, `Avg Pace`)) +
  geom_point(aes(color=Location,
                 size=Distance,
                 text=sprintf("Distance: %skm\nDuration: %sh\nElev Gain: %sm\nElev Loss: %sm", round(Distance, 2), round(Duration,2), `Elev Gain`, `Elev Loss`)),
             alpha=0.5) +
  geom_smooth(method="loess", span=0.1, se=FALSE, color="orangered", size=0.4) +
  ylim(c(4, 10)) +
  theme_light()
ggplotly(p, tooltip=c("text", "colour"))

So plotly does work.

Side Notes

  • blogdown is pretty easy to use. Yesterday I read the first chapter of the blogdown book, bought this domain name, registered an account at netlify, typed like 5 blogdown commands, pushed the site to github, linked the repo to netlify and that’s it. I still know nothing about Hugo, which I’m going to learn about in the second chapter of the blogdown book.

  • I recently realized a lot of R related tools I use are authored by Yihui Xie, 谢益辉, including knitr, xaringan, and this blogdown. Looked through his blog over the past like 10 years. 这是个人才啊。