Previously on "How has A State of Trance changed over time?" we poked the Spotify Web API and returned with every episode of A State of Trance. In this post, we'll examine how the show's BPM has changed over time.
First, some housekeeping items.
In the "Methodology" post we learned Spotify's catalogue of A State of Trance, while it seems to contain every episode, does not have every track in some episodes.
Due to the nature of averages, this will cause our calculations to be skewed somewhat. Filling in the blanks is left as an exercise for the reader.
Let's find the average BPM of each episode and graph it over time.
We'll ask Spotify for the BPM of every track in an episode, add it all up, and divide by the number of tracks - removing the voiceovers and interludes of course! For the first 10 episodes, this looks like:
episode_avg_bpm = []
for episode in episodes[:10]:
try:
episode_bpm = 0
tracks_counted = 0
for track in sp.album_tracks(episode['uri'])['items']:
if "a atate of trance" in track['name'].lower() or "- interview" in track['name'].lower():
continue
else:
episode_bpm += sp.audio_features(track['uri'])[0]['tempo']
tracks_counted += 1
avg = episode_bpm/tracks_counted
print(episode['name'], avg)
episode_avg_bpm.append(avg)
except:
pass
Rinse and repeat for 950+ episodes. Grab a tea or coffee, this could take a bit!
episode_avg_bpm = []
for episode in episodes:
try:
episode_bpm = 0
tracks_counted = 0
for track in sp.album_tracks(episode['uri'])['items']:
if "a state of trance" in track['name'].lower() or "- interview" in track['name'].lower():
continue
else:
episode_bpm += sp.audio_features(track['uri'])[0]['tempo']
tracks_counted += 1
avg = episode_bpm/tracks_counted
episode_avg_bpm.append(avg)
except:
pass
Instead of printing this, let's throw it into a quick Altair graph:
x = np.arange(len(episode_avg_bpm))
source = pd.DataFrame({
'episode': x,
'avg bpm': np.array(episode_avg_bpm)
})
alt.Chart(source).mark_line().encode(
alt.X('episode'),
alt.Y('avg bpm', scale=alt.Scale(domain=(120, 150))),
).properties(
title="A State of Trance - Average BPM of episode"
)
Episode 057 tops the charts at an impressive 148 BPM, why? Looking at the tracklist ..
"""
Artist: Armin van Buuren ASOT Radio
Album: A State Of Trance Episode 057
Album link: https://open.spotify.com/album/56qM5Y21wbvCW9l5GiAiaV
Album ID: 56qM5Y21wbvCW9l5GiAiaV
"""
episode_bpm = 0
tracks_counted = 0
for track in sp.album_tracks('56qM5Y21wbvCW9l5GiAiaV')['items']:
if "a state of trance" in track['name'].lower() or "- interview" in track['name'].lower():
continue
else:
print(track['artists'][0]['name'], '-', track['name'], sp.audio_features(track['uri'])[0]['tempo'])
episode_bpm += sp.audio_features(track['uri'])[0]['tempo']
tracks_counted += 1
print("Episode average: ", episode_bpm/tracks_counted)
UMEK - Gatex (Original Mix) clocks in at a whopping 184 BPM, drastically raising the average of this episode. Beatport reports it at 136, something's not right..
Finally, for fun, we can draw a line at 138 BPM to compare.
x = np.arange(len(episode_avg_bpm))
source = pd.DataFrame({
'episode': x,
'avg bpm': np.array(episode_avg_bpm)
})
source['138'] = 138
base = alt.Chart(source).mark_line().encode(
alt.X('episode'),
alt.Y('avg bpm', scale=alt.Scale(domain=(120, 150))),
).properties(
title="A State of Trance - Average BPM of episode"
)
rule = alt.Chart(source).mark_rule(color='red').encode(
y='138'
)
base + rule
And there we have it! There's plenty more to investigate beyond BPM, stay tuned..