This report analyzes velocity-based resistance training (VBRT) data from 6 athletes over the period from February 06, 2024 to April 11, 2024.
Key Findings:
# Upper body stats
upper_stats <- df %>%
filter(exercise_type == "Upper Body") %>%
group_by(athlete) %>%
summarise(
Total_Reps = n(),
Training_Sessions = n_distinct(date),
Avg_Mean_Power = round(mean(Conc.Mean.Power..W., na.rm = TRUE), 1),
Avg_Peak_Force = round(mean(Conc.Peak.Force..N., na.rm = TRUE), 1),
Avg_Velocity = round(mean(Conc.Mean.Velocity, na.rm = TRUE), 2),
.groups = 'drop'
)
# Lower body stats
lower_stats <- df %>%
filter(exercise_type == "Lower Body") %>%
group_by(athlete) %>%
summarise(
Total_Reps = n(),
Training_Sessions = n_distinct(date),
Avg_Mean_Power = round(mean(Conc.Mean.Power..W., na.rm = TRUE), 1),
Avg_Peak_Force = round(mean(Conc.Peak.Force..N., na.rm = TRUE), 1),
Avg_Velocity = round(mean(Conc.Mean.Velocity, na.rm = TRUE), 2),
.groups = 'drop'
)
cat("### Upper Body Performance Summary\n")
## ### Upper Body Performance Summary
knitr::kable(upper_stats,
col.names = c("Athlete", "Total Reps", "Sessions", "Avg Power (W)",
"Avg Peak Force (N)", "Avg Velocity (m/s)"))
| Athlete | Total Reps | Sessions | Avg Power (W) | Avg Peak Force (N) | Avg Velocity (m/s) |
|---|---|---|---|---|---|
| Brock Gowanlock | 296 | 12 | 432.3 | 1440.4 | 0.49 |
| Frederic CHAGNON | 91 | 7 | 475.5 | 1946.9 | 0.54 |
| Jamar McGLOSTER | 255 | 11 | 569.8 | 1766.8 | 0.52 |
| Marc-antoine DEQUOY | 78 | 5 | 534.8 | 1819.6 | 0.63 |
| Po LESTAGE | 361 | 15 | 573.4 | 1801.7 | 0.54 |
| Tyson Philpot | 27 | 2 | 379.1 | 1281.4 | 0.48 |
cat("\n### Lower Body Performance Summary\n")
##
## ### Lower Body Performance Summary
knitr::kable(lower_stats,
col.names = c("Athlete", "Total Reps", "Sessions", "Avg Power (W)",
"Avg Peak Force (N)", "Avg Velocity (m/s)"))
| Athlete | Total Reps | Sessions | Avg Power (W) | Avg Peak Force (N) | Avg Velocity (m/s) |
|---|---|---|---|---|---|
| Brock Gowanlock | 388 | 13 | 1299.0 | 3203.7 | 0.60 |
| Frederic CHAGNON | 234 | 11 | 1374.5 | 3146.8 | 0.62 |
| Jamar McGLOSTER | 63 | 5 | 1941.6 | 4971.9 | 0.55 |
| Marc-antoine DEQUOY | 78 | 5 | 1101.8 | 3147.9 | 0.47 |
| Po LESTAGE | 380 | 16 | 1693.4 | 3929.3 | 0.67 |
| Tyson Philpot | 96 | 4 | 1444.8 | 3110.4 | 0.67 |
# Calculate daily averages and 4-day moving average
daily_power <- df %>%
group_by(date, athlete, exercise_type) %>%
summarise(avg_power = mean(Conc.Mean.Power..W., na.rm = TRUE), .groups = 'drop') %>%
arrange(athlete, exercise_type, date) %>%
group_by(athlete, exercise_type) %>%
mutate(moving_avg_4_day = zoo::rollmean(avg_power, k = 4, fill = NA, align = "right")) %>%
filter(!is.na(moving_avg_4_day)) %>%
ungroup()
ggplot(daily_power, aes(x = date, y = moving_avg_4_day, color = athlete)) +
geom_line(size = 1.2, alpha = 0.8) +
geom_point(size = 2) +
facet_wrap(~exercise_type, ncol = 1, scales = "free_y") +
scale_y_continuous(labels = comma_format()) +
scale_x_date(date_labels = "%b %d", date_breaks = "1 week") +
labs(
title = "Mean Power Output Trends by Exercise Type (4-Day Moving Average)",
subtitle = "Upper and lower body power development over time",
x = "Date",
y = "Mean Power (Watts) - 4-Day MA",
color = "Athlete"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1),
strip.text = element_text(face = "bold", size = 12),
legend.position = "bottom"
)
ggplot(df, aes(x = Conc.Mean.Velocity, y = Conc.Peak.Force..N., color = athlete)) +
geom_point(alpha = 0.6, size = 1.5) +
geom_smooth(method = "lm", se = FALSE, size = 1.2) +
facet_grid(exercise_type ~ athlete, scales = "free") +
scale_y_continuous(labels = comma_format()) +
labs(
title = "Force-Velocity Relationship by Exercise Type and Athlete",
x = "Mean Velocity (m/s)",
y = "Peak Force (N)"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold"),
strip.text = element_text(face = "bold"),
legend.position = "none"
)
exercise_summary <- df %>%
count(exercise, exercise_type, sort = TRUE) %>%
group_by(exercise_type) %>%
slice_head(n = 6) %>%
ungroup()
ggplot(exercise_summary, aes(x = reorder(exercise, n), y = n, fill = exercise_type)) +
geom_col() +
coord_flip() +
facet_wrap(~exercise_type, scales = "free") +
geom_text(aes(label = n), hjust = -0.1, size = 3.5) +
scale_fill_manual(values = c("Upper Body" = "#3498db", "Lower Body" = "#e74c3c")) +
labs(
title = "Most Performed Exercises by Body Region",
x = "Exercise",
y = "Total Repetitions"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold"),
strip.text = element_text(face = "bold", size = 12),
legend.position = "none"
)
# Get top exercises for each category
top_exercises <- df %>%
count(exercise, exercise_type, sort = TRUE) %>%
group_by(exercise_type) %>%
slice_head(n = 4) %>%
pull(exercise)
df_top <- df %>% filter(exercise %in% top_exercises)
ggplot(df_top, aes(x = reorder(exercise, Conc.Mean.Power..W.),
y = Conc.Mean.Power..W., fill = exercise_type)) +
geom_boxplot(alpha = 0.8) +
coord_flip() +
facet_wrap(~exercise_type, scales = "free") +
scale_y_continuous(labels = comma_format()) +
scale_fill_manual(values = c("Upper Body" = "#3498db", "Lower Body" = "#e74c3c")) +
labs(
title = "Power Output Distribution by Exercise Type",
x = "Exercise",
y = "Mean Power Output (Watts)"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold"),
strip.text = element_text(face = "bold", size = 12),
legend.position = "none"
)
# Calculate 4-rep moving averages
power_ma <- df %>%
arrange(athlete, exercise_type, date, set.id) %>%
group_by(athlete, exercise_type) %>%
mutate(
rep_number = row_number(),
moving_avg_4 = zoo::rollmean(Conc.Mean.Power..W., k = 4, fill = NA, align = "right")
) %>%
filter(!is.na(moving_avg_4)) %>%
ungroup()
ggplot(power_ma, aes(x = rep_number, y = moving_avg_4, color = athlete)) +
geom_line(size = 1.2, alpha = 0.8) +
facet_grid(exercise_type ~ athlete, scales = "free") +
scale_y_continuous(labels = comma_format()) +
labs(
title = "Concentric Mean Power - 4-Rep Moving Average by Exercise Type",
x = "Repetition Number",
y = "Mean Power (Watts) - 4-Rep MA"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold"),
strip.text = element_text(face = "bold"),
legend.position = "none"
)
weekly_load <- df %>%
mutate(week = floor_date(date, "week")) %>%
group_by(week, athlete, exercise_type) %>%
summarise(total_volume = sum(total.weight..kg., na.rm = TRUE), .groups = 'drop')
ggplot(weekly_load, aes(x = week, y = total_volume, fill = athlete)) +
geom_col(position = "stack", alpha = 0.8) +
facet_wrap(~exercise_type, ncol = 1, scales = "free_y") +
scale_y_continuous(labels = comma_format(suffix = " kg")) +
scale_x_date(date_labels = "%b %d", date_breaks = "1 week") +
labs(
title = "Weekly Training Volume by Exercise Type",
x = "Week",
y = "Total Volume (kg)",
fill = "Athlete"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 16, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1),
strip.text = element_text(face = "bold", size = 12),
legend.position = "bottom"
)
# Calculate metrics
total_volume_upper <- sum(filter(df, exercise_type == "Upper Body")$total.weight..kg., na.rm = TRUE)
total_volume_lower <- sum(filter(df, exercise_type == "Lower Body")$total.weight..kg., na.rm = TRUE)
metrics_summary <- data.frame(
Metric = c("Upper Body Training Volume", "Lower Body Training Volume",
"Training Period", "Total Athletes"),
Value = c(
paste(format(total_volume_upper, big.mark = ","), "kg"),
paste(format(total_volume_lower, big.mark = ","), "kg"),
paste(format(min(df$date), "%b %d"), "-", format(max(df$date), "%b %d, %Y")),
length(unique(df$athlete))
)
)
knitr::kable(metrics_summary,
col.names = c("Key Performance Indicator", "Value"))
| Key Performance Indicator | Value |
|---|---|
| Upper Body Training Volume | 111,172.4 kg |
| Lower Body Training Volume | 301,142.8 kg |
| Training Period | Feb 06 - Apr 11, 2024 |
| Total Athletes | 6 |
Based on the analysis of this VBRT data:
Training Optimization: - Monitor individual force-velocity profiles for upper and lower body separately - Track power output trends by exercise type to identify training adaptations - Consider exercise-specific power targets based on observed distributions
Performance Monitoring: - Weekly volume tracking shows training consistency across movement patterns - Power output correlations suggest effective load management - Individual athlete profiles indicate personalized training responses
Future Analysis: - Implement fatigue monitoring through velocity loss thresholds - Track training adaptations over longer periods - Analyze exercise-specific progression patterns
Report generated on 2025-09-08 using VBRT data from 2347 training repetitions.