Here is some updated R code from my previous post. It doesn't throw any warnings when importing tracks with and without heart rate information. Also, it is easier to distinguish types of tracks now (e.g., when you want to plot runs and rides separately). Another thing I changed: You get very basic information on the track when you click on it (currently the name of the track and the total length).
Have fun and leave a comment if you have any questions.
options(stringsAsFactors = F)
rm(list=ls())
library(httr)
library(rjson)
library(leaflet)
library(dplyr)
token <- "<your Strava API token>"
# Functions ---------------------------------------------------------------
get.coord.df.from.stream <- function (stream.obj) {
data.frame(lat = sapply(stream.obj[[1]]$data, USE.NAMES = F, FUN = function (x) x[[1]]),
lon = sapply(stream.obj[[1]]$data, USE.NAMES = F, FUN = function (x) x[[2]]))
}
get.stream.from.activity <- function (act.id, token) {
stream <- GET("https://www.strava.com/",
path = paste0("api/v3/activities/", act.id, "/streams/latlng"),
query = list(access_token = token))
content(stream)
}
get.activities2 <- function (token) {
activities <- GET("https://www.strava.com/", path = "api/v3/activities",
query = list(access_token = token, per_page = 200))
activities <- content(activities, "text")
activities <- fromJSON(activities)
res.df <- data.frame()
for (a in activities) {
values <- sapply(c("name", "distance", "moving_time", "elapsed_time", "total_elevation_gain",
"type", "id", "start_date_local",
"location_country", "average_speed", "max_speed", "has_heartrate", "elev_high",
"elev_low", "average_heartrate", "max_heartrate"), FUN = function (x) {
if (is.null(a[[x]])) {
NA } else { a[[x]] }
})
res.df <- rbind(res.df, values)
}
names(res.df) <- c("name", "distance", "moving_time", "elapsed_time", "total_elevation_gain",
"type", "id", "start_date_local",
"location_country", "average_speed", "max_speed", "has_heartrate", "elev_high",
"elev_low", "average_heartrate", "max_heartrate")
res.df
}
get.multiple.streams <- function (act.ids, token) {
res.list <- list()
for (act.id.i in 1:length(act.ids)) {
if (act.id.i %% 5 == 0) cat("Actitivy no.", act.id.i, "of", length(act.ids), "\n")
stream <- get.stream.from.activity(act.ids[act.id.i], token)
coord.df <- get.coord.df.from.stream(stream)
res.list[[length(res.list) + 1]] <- list(act.id = act.ids[act.id.i],
coords = coord.df)
}
res.list
}
activities <- get.activities2(token)
stream.list <- get.multiple.streams(activities$id, token)
# Leaflet -----------------------------------------------------------------
lons.range <- c(9.156572, 9.237580)
lats.range <- c(48.74085, 48.82079)
map <- leaflet() %>%
addProviderTiles("OpenMapSurfer.Grayscale", # nice: CartoDB.Positron, OpenMapSurfer.Grayscale, CartoDB.DarkMatterNoLabels
options = providerTileOptions(noWrap = T)) %>%
fitBounds(lng1 = min(lons.range), lat1 = max(lats.range), lng2 <- max(lons.range), lat2 = min(lats.range))
add.run <- function (act.id, color, act.name, act.dist, strlist = stream.list) {
act.ind <- sapply(stream.list, USE.NAMES = F, FUN = function (x) {
x$act.id == act.id
})
act.from.list <- strlist[act.ind][[1]]
map <<- addPolylines(map, lng = act.from.list$coords$lon,
lat = act.from.list$coords$lat,
color = color, opacity = 1/3, weight = 2,
popup = paste0(act.name, ", ", round(as.numeric(act.dist) / 1000, 2), " km"))
}
# plot all
for (i in 1:nrow(activities)) {
add.run(activities[i, "id"], ifelse(activities[i, "type"] == "Run", "red",
ifelse(activities[i, "type"] == "Ride", "blue", "black")),
activities[i, "name"], activities[i, "distance"])
}
map

Jan
18
Rcrastinate is moving.
Hi all, this is just an announcement.
I am moving Rcrastinate to a blogdown-based solution and am therefore leaving blogger.com. If you're interested in the new setup and how you could do the same yourself, please check out the all shiny and new Rcrastinate over at
http://rcrastinate.rbind.io/
In my first post over there, I am giving a short summary on how I started the whole thing. I hope that the new Rcrastinate is also integrated into R-bloggers soon.
Thanks for being here, see you over there.
I am moving Rcrastinate to a blogdown-based solution and am therefore leaving blogger.com. If you're interested in the new setup and how you could do the same yourself, please check out the all shiny and new Rcrastinate over at
http://rcrastinate.rbind.io/
In my first post over there, I am giving a short summary on how I started the whole thing. I hope that the new Rcrastinate is also integrated into R-bloggers soon.
Thanks for being here, see you over there.
Jan
12
10 years of playback history on Last.FM: "Just sit back and listen"
Alright, seems like this is developing into a blog where I am increasingly investigating my own music listening habits.
Recently, I've come across the analyzelastfm package by Sebastian Wolf. I used it to download my complete listening history from Last.FM for the last ten years. That's a complete dataset from 2009 to 2018 with exactly 65,356 "scrobbles" (which is the word Last.FM uses to describe one instance of a playback of a song).
Recently, I've come across the analyzelastfm package by Sebastian Wolf. I used it to download my complete listening history from Last.FM for the last ten years. That's a complete dataset from 2009 to 2018 with exactly 65,356 "scrobbles" (which is the word Last.FM uses to describe one instance of a playback of a song).
Dec
30
This dance, it's like a weapon: Radiohead's and Beck's danceability, valence, popularity, and more from the LastFM and Spotify APIs
Giddy up, giddy it up
Wanna move into a fool's gold room
With my pulse on the animal jewels
Of the rules that you choose to use to get loose
With the luminous moves
Bored of these limits, let me get, let me get it like
Wow!
When it comes to surreal lyrics and videos, I'm always thinking of Beck. Above, I cited the beginning of the song "Wow" from his latest album "Colors" which has received rather mixed reviews. In this post, I want to show you what I have done with Spotify's API.
Wanna move into a fool's gold room
With my pulse on the animal jewels
Of the rules that you choose to use to get loose
With the luminous moves
Bored of these limits, let me get, let me get it like
Wow!
When it comes to surreal lyrics and videos, I'm always thinking of Beck. Above, I cited the beginning of the song "Wow" from his latest album "Colors" which has received rather mixed reviews. In this post, I want to show you what I have done with Spotify's API.
Sep
12
Network visualization of football transfers using the 'visNetwork' package
Click here for the interactive visualization
If you're interested in the visualisation of networks or graphs, you might've heard of the great package "visNetwork". I think it's a really great package and I love playing around with it. The scenarios of graph-based analyses are many and diverse: whenever you can describe your data in terms of "outgoing" and "receiving" entities, a graph-based analysis and/or visualisation is possible.
If you're interested in the visualisation of networks or graphs, you might've heard of the great package "visNetwork". I think it's a really great package and I love playing around with it. The scenarios of graph-based analyses are many and diverse: whenever you can describe your data in terms of "outgoing" and "receiving" entities, a graph-based analysis and/or visualisation is possible.
May
6
Send tweets from R: A very short walkthrough
There are a few reasons why you might want to send tweets from R. You might want to write a Twitter bot or - as in my case - you want to send yourself a tweet when a very long computation finishes.
So, here I will run you through all the steps you have to take using
- Twitter's API and
- the twitteR package written by Jeff Gentry
The setup to send myself tweets is the following: I have my main twitter account and an additional account I am only using to tweet from R.
So, here I will run you through all the steps you have to take using
- Twitter's API and
- the twitteR package written by Jeff Gentry
The setup to send myself tweets is the following: I have my main twitter account and an additional account I am only using to tweet from R.
May
1
Get your tracks from the Strava API and plot them on Leaflet maps
Here is some updated R code from my previous post. It doesn't throw any warnings when importing tracks with and without heart rate information. Also, it is easier to distinguish types of tracks now (e.g., when you want to plot runs and rides separately). Another thing I changed: You get very basic information on the track when you click on it (currently the name of the track and the total length).
Have fun and leave a comment if you have any questions.
Have fun and leave a comment if you have any questions.
Jan
31
Where do you run to? Map your Strava activities on static and Leaflet maps.
So, Strava's heatmap made quite a stir the last few weeks. I decided to give it a try myself. I wanted to create some kind of "personal heatmap" of my runs, using Strava's API. Also, combining the data with Leaflet maps allows us to make use of the beautiful map tiles supported by Leaflet and to zoom and move the maps around - with the runs on it, of course.
So, let's get started. First, you will need an access token for Strava's API.
So, let's get started. First, you will need an access token for Strava's API.
Oct
27
Substitute levels in a factor or character vector
I've been using the ggplot2 package a lot recently. When creating a legend or tick marks on the axes, ggplot2 uses the levels of a character or factor vector. Most of the time, I am working with coded variables that use some abbreviation of the "true" meaning (e.g. "f" for female and "m" for male or single characters for some single character for a location: "S" for Stuttgart and "M" for Mannheim).
In my plots, I don't want these codes but the full name of the level.
In my plots, I don't want these codes but the full name of the level.
Mar
20
What's in the words? Comparing artists and lyrics with R.
It's been a while since I had the opportunity to post something on music. Let's get back to that.
I got my hands on some song lyrics by a range of artists. (I have an R script to download all lyrics for a given artist from a lyrics website.
I got my hands on some song lyrics by a range of artists. (I have an R script to download all lyrics for a given artist from a lyrics website.
Aug
5
Plotting GPX tracks with Shiny and Leaflet
Lately, I got the chance to play around with Shiny and Leaflet a lot - and it is really fun! So I decided to catch up on an old post of mine and build a Shiny application where you can upload your own GPX files and plot them directly in the browser.
Of course, you will need some GPX file to try it out. You can get an example file here (you gonna need to save it in a .gpx file with a text editor, though). Also, the Shiny application will always plot the first track saved in a GPX file.
Of course, you will need some GPX file to try it out. You can get an example file here (you gonna need to save it in a .gpx file with a text editor, though). Also, the Shiny application will always plot the first track saved in a GPX file.
View comments