The rStrava package allows easy access to your Strava data using the Strava API. Combined with leaflet I can easily create a heatmap of all of my Strava activities. One interesting challenge does arise when doing this. Strava stores the coordinates of the activity as a Google Polyline, so I will use the googleway package to decode the data in to latitude and longitude coordinates.
First, I load in all the necessary packages.
# Code written by Daniel Cullen# Using code from the following sources:# https://padpadpadpad.github.io/post/animate-your-strava-activities-using-rstrava-and-gganimate/ # https://medium.com/@annthurium/getting-started-with-the-strava-api-a-tutorial-f3909496cd2d # https://www.r-bloggers.com/where-do-you-run-to-map-your-strava-activities-on-static-and-leaflet-maps/ # http://www.databrew.cc/posts/strava.html # https://github.com/fawda123/rStravalibrary(rStrava) # devtools::install_github('fawda123/rStrava') library(dplyr)library(leaflet)library(htmlwidgets)library(googleway) # to convert google polyline format to lat and longThen I will enter my personal Strava API information which can be found here after you apply for API access.
## Necessary info from Strava api https://www.strava.com/settings/api app_name <- '<>' # chosen by userapp_client_id <- '<>' # an integer, assigned by Stravaapp_secret <- '<>' # an alphanumeric secret, assigned by Stravastoken <- httr::config(token = strava_oauth(app_name, app_client_id, app_secret, app_scope="activity:read_all"))Next, I load in my activity list and compile my activities into a data frame using the rStrava library.
## Load my activities and compile activities with rStrava librarymy_data <- get_activity_list(stoken)act_data <- compile_activities(my_data)The activity data contains 56 variables. We only need to keep two, the map data called 'map.summary_polyline' and the 'upload_id'.
## Keep only activity id and map linekeeps <- c('map.summary_polyline', 'upload_id')my_acts <- dplyr::select(act_data, match(keeps, names(act_data)))Now that the data is prepared I want to create a blank map of the area I want to include in my map. I create longitude and latitude bounds to create the map area I want. This will take some trial and error to get the exact bounds that you want.
## Create blank map bounded by given lon and latlons.range <- c(-119.9, -119.6)lats.range <- c(34.3, 34.58)## tile options CartoDB.Positron , CartoDB.DarkMatter , Stamen.Toner map <- leaflet(options = leafletOptions(zoomControl = FALSE)) %>% addProviderTiles('CartoDB.Positron', options = providerTileOptions(noWrap = T, minZoom=12, maxZoom=12)) %>% fitBounds(lng1 = min(lons.range), lat1 = max(lats.range), lng2 <- max(lons.range), lat2 = min(lats.range))map #save using mapshot(map, file="sbmap.png")Next I loop through all my activities and convert them from Google Polylines to a dataframe of longitudes and latitudes each loop through will add one activity to the map.
loop <- unique(my_acts$upload_id)for (i in loop) { activity <- filter(my_acts, upload_id == i) coords <- googleway::decode_pl(activity$map.summary_polyline) map <- addPolylines(map, lng = coords$lon, lat = coords$lat, color = 'blue', opacity = 1/4, weight = 2)}mapFinally, to export the final interactive map as seen at the top of the page I use the saveWidget command from the htmlwidgets package.
saveWidget(map, file="runningmap.html")