Introduction

We've previously looked at A State of Trance's average episode BPM, most-played artists and most-played tracks overall.

Starting with this post we'll do the same - but looking at things from year-to-year. Let's begin with annual average episode BPM.

Getting Started

len(episodes)
963

episodes of across its nearly 20-year run. As of writing, according to Spotify, etc ..

As a weekly radio show, I'd expect to see about 52 episodes air each year. Is that correct?

Fortunately Spotify can tell us when an episode aired:

for episode in episodes[:10]:
    print(episode['name'], episode['release_date'])
A State Of Trance Episode 000 2001-05-17
A State Of Trance Episode 001 2001-05-31
A State Of Trance Episode 002 2001-06-07
A State Of Trance Episode 003 2001-06-14
A State Of Trance Episode 004 2001-06-21
A State Of Trance Episode 005 2001-06-28
A State Of Trance Episode 006 2001-07-19
A State Of Trance Episode 007 2001-07-26
A State Of Trance Episode 008 2001-08-02
A State Of Trance Episode 009 2001-08-09

So we can keep a running tally for each year, then print the result:

from collections import defaultdict

episodes_counter = defaultdict(int)

for episode in episodes:
    episodes_counter[episode['release_date'][:4]] += 1

print(dict(episodes_counter))
{'2001': 27, '2002': 50, '2003': 50, '2004': 52, '2005': 48, '2006': 50, '2007': 51, '2008': 51, '2009': 51, '2010': 50, '2011': 52, '2012': 51, '2013': 51, '2014': 51, '2015': 52, '2016': 50, '2017': 51, '2018': 52, '2019': 52, '2020': 21}

Seems reasonable enough!

Calculating

Let's crunch some numbers.

What is the annual average episode BPM?

annual_total_bpm = defaultdict(int)
annual_avg_bpm = defaultdict(int)

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
        episodes_counted += 1
        avg = episode_bpm/tracks_counted
        annual_total_bpm[episode['release_date'][:4]] += avg
    except:
        pass

for year, avg in annual_total_bpm.items():
    annual_avg_bpm[year] = avg / episodes_counter[year]

print(dict(annual_avg_bpm))
{'2001': 137.34653042328043, '2002': 138.77037672527473, '2003': 137.87648184593183, '2004': 136.8379514048452, '2005': 135.9946882254463, '2006': 136.21986194104406, '2007': 135.31834901771512, '2008': 134.5739768988312, '2009': 134.84276103847634, '2010': 134.2873634011065, '2011': 133.38769823050973, '2012': 133.77641000308137, '2013': 134.89472557606408, '2014': 134.62926964078503, '2015': 133.21748777702336, '2016': 133.8357659060619, '2017': 133.83226986060524, '2018': 132.8617358100079, '2019': 133.39046580493476, '2020': 133.46879858547982}

Results

Let's see what we've got!

source = pd.DataFrame([(k, v) for k, v in annual_avg_bpm.items()], 
                   columns=['Year', 'Average Episode BPM'])
source['138'] = 138

base = alt.Chart(source).mark_line().encode(
    x=alt.X('Year'),
    y=alt.Y('Average Episode BPM', scale=alt.Scale(domain=(130, 140))),
).properties(
    title="A State of Trance - Annual Average BPM of Episode",
    width=600
)

rule = alt.Chart(source).mark_rule(color='red').encode(
    y='138'
)

base + rule

Straightforward enough. In the coming posts we'll do something similar, looking at the most-played artists and tracks each year.