This is the development repository for Athlytics, an R package designed to simplify the analysis of athletic performance and training load data sourced directly from the Strava API. The package provides functions for fetching your Strava data, calculating key metrics, and generating insightful visualizations for training monitoring.
For details on recent changes and version history, please see the Changelog on the package website.
You can install the released version of Athlytics from CRAN (once available) with:
install.packages("Athlytics")
Alternatively, the development version from this repository can be installed as follows:
# install.packages('remotes')
::install_github('HzaCode/Athlytics') remotes
library(Athlytics)
rStrava
)Athlytics
requires you to authenticate
with Strava using the rStrava
package. This generates a
token that you then pass to Athlytics
functions.
localhost
.rStrava::strava_oauth()
:
Token2.0
object needed by
Athlytics
.cache = TRUE
(default) to store
the token securely (in .httr-oauth
), avoiding
re-authentication in later sessions.Note: Running strava_oauth()
may open a browser window
for you to log in to Strava and authorize the application.
library(Athlytics)
# Sys.setenv(STRAVA_CLIENT_ID = "YOUR_CLIENT_ID")
# Sys.setenv(STRAVA_CLIENT_SECRET = "YOUR_SECRET")
# --- Authentication Step ---
<- 'MyAthlyticsApp' # Choose a name
app_name <- Sys.getenv("STRAVA_CLIENT_ID")
client_id <- Sys.getenv("STRAVA_CLIENT_SECRET")
client_secret
# Authenticate using rStrava and STORE the token object
# Make sure app_scope allows reading activities.
<- rStrava::strava_oauth(app_name,
stoken app_client_id = client_id, # Use app_client_id
app_secret = client_secret, # Use app_secret
app_scope = "activity:read_all", # Or specific scope needed
cache = TRUE) # IMPORTANT for reusing the token
While most functions rely on data directly available from Strava (like duration, distance, heart rate), some advanced calculations or metrics may require additional user-specific information.
user_ftp
(Numeric): Your Functional Threshold Power (in
Watts). Needed for calculating TSS (approximate) or power zones for
cycling/running with power.user_max_hr
(Numeric): Your maximum heart rate. Needed
for calculating HRSS (approximate).user_resting_hr
(Numeric): Your resting heart rate.
Also needed for calculating HRSS (approximate).(Provide these parameters directly to the Athlytics function call
if the chosen load_metric
or analysis requires them. Check
function documentation for details.)
These functions generate plots to analyze trends and performance,
using data fetched and processed from Strava via the stoken
you provide.
Important Note on API Usage and Performance: Some
functions, particularly calculate_pbs
(which needs to fetch
detailed data for each activity) and calculate_decoupling
(which now uses httr
to directly fetch detailed activity
streams), can be slow and may hit Strava API rate
limits (leading to errors) if you analyze a large number of activities.
Consider using the max_activities
parameter in these
functions or analyzing shorter date ranges if you encounter issues.
This analysis provides an intuitive way to assess your current
training load status and potential injury risk level by plotting acute
vs. chronic load. You can clearly see where your load combination falls
within defined risk zones (like the sweet spot, caution zone, or danger
zone). Note: When using TSS or HRSS as the
load_metric
, the calculation is an approximation
based on average power or average heart rate available from the Strava
activity summary, not detailed stream data (which would be much slower
to process).
Calculating Data: To get the underlying data (date, daily_load, atl, ctl, acwr) as a data frame without plotting:
# Ensure stoken is a valid token object from rStrava::strava_oauth()
# Ensure user_ftp = 280 is appropriate for the user
<- calculate_exposure(
exposure_data stoken = stoken,
activity_type = "Ride", # Example: Target Rides
load_metric = "tss", # Example: Use approximate TSS based on average power
user_ftp = 280, # REQUIRED for TSS
acute_period = 7,
chronic_period = 28
)# print(tail(exposure_data)) # Uncomment to view
Plotting:
# Example using approximated TSS based on avg power for Rides
# Ensure stoken is valid and user_ftp = 280 is correct
plot_exposure(
stoken = stoken,
activity_type = "Ride", # Specify activity type(s)
load_metric = "tss", # Use approximate TSS
user_ftp = 280, # REQUIRED for TSS
acute_period = 7, # Duration (days) for acute load calculation
chronic_period = 28 # Duration (days) for chronic load calculation
# , end_date = Sys.Date() # Optional
# , risk_zones = TRUE # Optional
)
# Example using approximate HRSS based on avg heart rate for Runs
# Ensure stoken is valid and HR parameters are correct
plot_exposure(
stoken = stoken,
activity_type = "Run", # Specify activity type(s)
load_metric = "hrss", # Use approximate HRSS
user_max_hr = 190, # REQUIRED for HRSS
user_resting_hr = 50, # REQUIRED for HRSS
acute_period = 7, # Duration (days) for acute load calculation
chronic_period = 42 # Example: Longer chronic window
# , end_date = Sys.Date() # Optional
# , risk_zones = TRUE # Optional
)
# Alternatively, plot pre-calculated data:
# plot_exposure(exposure_df = exposure_data)
With this analysis, you can monitor the rate of change in your
training load over time, helping to identify periods of rapid increases
that might lead to overtraining or heightened injury risk. It’s a
valuable tool for periodized training monitoring and risk management.
Note: While calculate_exposure
also calculates ACWR as
part of its output, this calculate_acwr
function focuses
specifically on the ACWR metric and its associated plot.
Calculating Data: To get the underlying ACWR data (date, acwr, acwr_smooth) as a data frame:
# Ensure stoken is valid
<- calculate_acwr(
acwr_data stoken = stoken,
activity_type = "Run",
load_metric = "duration_mins",
acute_period = 7,
chronic_period = 28
)# print(tail(acwr_data)) # Uncomment to view
Plotting:
# Ensure stoken is valid
plot_acwr(
stoken = stoken,
activity_type = "Run", # Specify activity type(s), e.g., "Run", "Ride", NULL for all
load_metric = "duration_mins", # Choose metric: "duration_mins", "distance_km", "elapsed_time_mins", "tss", "hrss", "elevation_gain_m"
acute_period = 7, # Duration (days) for acute load calculation
chronic_period = 28 # Duration (days) for chronic load calculation
# , start_date = NULL # Optional: Start date (YYYY-MM-DD) for analysis (defaults to 1 year ago)
# , end_date = NULL # Optional: End date (YYYY-MM-DD) for analysis (defaults to today)
# , user_ftp = NULL # Optional: Required if load_metric = "tss"
# , user_max_hr = NULL # Optional: Required if load_metric = "hrss"
# , user_resting_hr = NULL # Optional: Required if load_metric = "hrss"
# , smoothing_period = 7 # Optional: Days for smoothing the ACWR line (defaults to 7)
# , highlight_zones = TRUE # Optional: Show background risk zone shading (defaults to TRUE)
)
# Alternatively, plot pre-calculated data:
# plot_acwr(acwr_df = acwr_data)
The Efficiency Factor (EF) is a common metric for assessing aerobic fitness adaptations. Ideally, EF should trend upwards as fitness improves, indicating higher output for the same physiological cost. This analysis helps track long-term aerobic efficiency progress and may signal accumulating fatigue or fluctuations in form.
Calculating Data: To get the underlying EF data (date, activity_type, ef_value) as a data frame:
# Ensure stoken is valid
<- calculate_ef(
ef_data stoken = stoken,
activity_type = c("Run", "Ride"), # Example: Runs and Rides
ef_metric = "Pace_HR" # Example: Pace/HR
)# print(tail(ef_data)) # Uncomment to view
Plotting:
# Ensure stoken is valid
plot_ef(
stoken = stoken,
activity_type = c("Run", "Ride"), # Specify activity type(s)
ef_metric = "Pace_HR" # Choose metric: "Pace_HR", "Power_HR"
# , start_date = NULL # Optional
# , end_date = NULL # Optional
# , min_duration_mins = 20 # Optional
# , add_trend_line = TRUE # Optional
# , smoothing_method = "loess" # Optional
)
# Alternatively, plot pre-calculated data:
# plot_ef(ef_df = ef_data)
This analysis allows you to visualize the progression of your key performance benchmarks over extended periods. Track metrics like your estimated best times for standard distances (e.g., 1k, 5k, 10k) or critical power outputs. By observing these trends, including highlighted Personal Bests (PBs), you can directly assess the effectiveness of different training blocks, validate fitness improvements beyond physiological markers, identify performance plateaus, and stay motivated by seeing concrete results align with your goals.
Calculating Data: To get the underlying PB data (activity_id, activity_date, distance, time_seconds, cumulative_pb_seconds, is_pb, etc.) as a data frame:
# Ensure stoken is valid
<- calculate_pbs(
pb_data stoken = stoken,
distance_meters = c(1000, 5000, 10000), # Example: 1k, 5k, 10k
activity_type = "Run" # Example: For Runs
)# print(tail(pb_data)) # Uncomment to view
# Filter for actual new PBs
# new_pbs <- pb_data[pb_data$is_pb, ]
# print(new_pbs)
Plotting:
# Ensure stoken is valid
plot_pbs(
stoken = stoken,
distance_meters = c(1000, 5000, 10000), # Specify distances in meters (REQUIRED)
activity_type = "Run" # Specify activity type (currently only "Run" is fully supported)
# , max_activities = 100 # Optional: Limit activities to check for speed/API limits
# , date_range = NULL # Optional
)
# Alternatively, plot pre-calculated data:
# plot_pbs(pbs_df = pb_data)
Note: This analysis requires fetching detailed
stream data for each activity (calculate_decoupling
uses
httr
for this) and can be very slow or hit API rate limits.
Use the max_activities
parameter to limit the scope.
Calculating Data: To get the underlying decoupling data (date, decoupling) as a data frame:
# Ensure stoken is valid.
<- calculate_decoupling(
decoupling_data stoken = stoken,
activity_type = "Run",
decouple_metric = "Pace_HR",
max_activities = 20 # Use a small number for example
)
# Check the result (it might be NULL or stop with an error if issues occurred)
# print(tail(decoupling_data))
Plotting:
# Ensure stoken is valid.
# WARNING: Can be slow. Reduce max_activities for plotting.
plot_decoupling(
stoken = stoken,
activity_type = "Run",
decouple_metric = "Pace_HR",
max_activities = 20 # Use a small number for example
)# Alternatively, plot pre-calculated data (if 'decoupling_data' was successfully calculated earlier):
# plot_decoupling(decoupling_df = decoupling_data)
Athlytics is under active development. We encourage a welcoming and inclusive environment, please see our Contributing Guidelines for guidelines on community interaction. While core functionalities are tested, variations in Strava data availability or unforeseen API interactions might occasionally lead to warnings or errors during execution. We appreciate bug reports and contributions to improve robustness!