Last active
January 19, 2025 10:46
-
-
Save PatrickStotz/05fbbc6c2db6c118249f834c2799a22b to your computer and use it in GitHub Desktop.
Plotting daily step count as a radial chart in R/ggplot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
####### Package management ####### | |
## install and load needs, if not yet present | |
# install.packages("needs") | |
# library(needs) | |
## packages used in this markdown document | |
## install these packages from github | |
# devtools::install_github("mrkaye97/fitbitr") | |
# devtools::install_github("AllanCameron/geomtextpath") | |
needs(tidyverse, viridis, fitbitr, geomtextpath) | |
####### get the data ####### | |
# downloading step count for 2024 from the fitbit API with the fitbitr package | |
# see here for setup instructions https://github.com/mrkaye97/fitbitr | |
steps = get_steps("2024-01-01", "2024-12-31") | |
####### data preparation ####### | |
# column charts in R/ggplot don't support gradual filling | |
# we turn the data into segments with 100 steps each and later plot them as tiles | |
steps_tiled = map2_dfr(steps$date, steps$steps, function(date, steps){ | |
date = date | |
segments_count = round(steps / 100) | |
df = tibble(date = date, segment = seq(0, segments_count)) | |
return(df) | |
}) | |
# preparing a grid for vertical grid lines | |
grid_x = tibble( | |
x = seq(ymd("2024-01-01"), ymd("2024-12-31"), "month"), | |
xend = seq(ymd("2024-01-01"), ymd("2024-12-31"), "month"), | |
y = rep(0, 12), | |
yend = rep(285, 12), # manually setting max. value after checking my max. step coutn | |
mid = seq(ymd("2024-01-15"), ymd("2024-12-15"), "month"),) %>% | |
add_row(x = ymd("2024-12-31"), y = 0, xend = ymd("2024-12-31"), yend = 285, mid = NA) %>% | |
print() | |
# preparing label text | |
labels = tibble(x = rep(ymd("2023-12-01"), 5), | |
y = c(50, 100, 150, 200, 250), | |
label = c("5,000", "10,000", "15,000", "20,000", "25,000 steps a day")) | |
# preparing colors | |
col_white = "#F4F4F3" | |
col_grey = "#DBDBDA" | |
col_black = "#0f0f0f" | |
####### generating plot ####### | |
ggplot(steps_tiled) + | |
# vertical grid lines | |
geom_segment(data = grid_x, aes(x = x, y = y, xend = xend, yend = yend), | |
linetype = "dashed", colour = col_grey,linewidth = 0.35) + | |
# horizontal grid lines | |
geom_hline(yintercept = c(100, 200), colour = col_grey, linewidth = 0.275) + | |
geom_hline(yintercept = c(50, 150, 250), colour = col_grey, linewidth = 0.125) + | |
# curved y-axis labels | |
geom_labelpath(data = labels, aes(x = x, y = y, label = label), | |
size = rel(2.95), hjust = 1, vjust = 1.2, colour = col_white, family = "Monaco", | |
fill = col_black, linewidth = 0, label.padding = 0) + | |
# tiles with a column look | |
geom_tile(aes(x = date, y = segment, fill = segment, color = segment), linewidth = 0.05) + | |
scale_fill_viridis_c(option = "B", begin = 0.09) + | |
scale_color_viridis_c(option = "B", begin = 0.09) + | |
# thin outlines for each pseudo-column with decreasing line width towards the center | |
geom_linerange(aes(x = c(date - 0.5), ymin = segment - 0.5, ymax = segment + 0.5, linewidth = segment), colour = col_black) + | |
geom_linerange(aes(x = c(date + 0.5), ymin = segment - 0.5, ymax = segment + 0.5, linewidth = segment), colour = col_black) + | |
scale_linewidth_continuous(range = c(0.0001, 0.25)) + | |
# labels for each month, positioned in the middle of the month sectors | |
scale_x_date(breaks = grid_x$mid, date_labels = "%b", limits = c(ymd("2023-12-01"), NA)) + | |
# turning the plot into a semi-circle polar plot | |
# adding inner radius simply for the look and setting start/end so we | |
# have one additional sector for y-axis labels | |
coord_radial(inner.radius = 0.125, start = -31/365 * pi, end = pi * 365.5/365, expand = F) + | |
# caption | |
labs(caption = "All my steps in 2024", x = "", y = "") + | |
# style, style, style | |
theme_minimal(base_family = "Gloucester MT Extra Condensed", base_size = 18) %+replace% | |
theme( | |
plot.caption = element_text(hjust = 0.5, vjust = 5, colour = col_white, size = rel(3.2)), | |
plot.background = element_rect(fill = col_black, size = 0), | |
plot.margin = margin(0, 0, 0, 0, unit = "cm"), | |
axis.text.x = element_text(face = "italic", colour = col_white, size = rel(1.55)), | |
axis.title.y = element_blank(), | |
axis.text.y = element_blank(), | |
panel.background = element_rect(fill = col_black, size = 0), | |
panel.grid = element_blank(), | |
legend.position = "none") | |
ggsave("steps_2024.png", width = 5, height = 8.55, scale = 1.5, dpi = 600) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment