NDP Songs - Spotify audio features analysis

Setup

First of all, register Your Application With Spotify. In order to access certain features of the Web API, we need to tell spotify that we're a legitimate app. To do this, go to https://developer.spotify.com/my-applications and create a new Application.

For the Redirect URI, add http://localhost/

From that page, copy your ClientId and your ClientSecret.

You need to set your Spotify API credentials. You can do this by setting environment variables like so:

Go to https://plot.ly/settings/api#/ and get api key.

os.environ['SPOTIPY_CLIENT_ID'] = 'your-spotify-client-id'
os.environ['SPOTIPY_CLIENT_SECRET'] = 'your-spotify-client-secret'
os.environ['SPOTIPY_REDIRECT_URI' ] = 'http://localhost/'
In [1]:
import numpy as np
import pandas as pd
from sklearn.preprocessing import minmax_scale
from sklearn.preprocessing import StandardScaler
import spotipy
import random
import os
import requests
import spotipy.util as util
from requests.auth import HTTPBasicAuth
import matplotlib.pyplot as plt
from matplotlib import font_manager
from math import pi
In [2]:
SPOTIPY_CLIENT_ID = os.environ.get('SPOTIPY_CLIENT_ID')
SPOTIPY_CLIENT_SECRET = os.environ.get('SPOTIPY_CLIENT_SECRET')
SPOTIPY_REDIRECT_URI = os.environ.get('SPOTIPY_REDIRECT_URI')

Get the access token for the app given the code¶

In [3]:
# Get token 
token = util.oauth2.SpotifyClientCredentials(client_id=SPOTIPY_CLIENT_ID, client_secret=SPOTIPY_CLIENT_SECRET)
cache_token = token.get_access_token()
spotify = spotipy.Spotify(cache_token)

Read CSV

In [4]:
origin_df = pd.read_csv("./spotify-id.csv")
origin_df = pd.DataFrame(origin_df)
origin_df
Out[4]:
year title spotify_id
0 1985 Stand Up for Singapore 2aIkiuxUesXTGU756fBJYD
1 1986 Count on Me, Singapore 3dY7P7YoGU0gYMmFs1krC1
2 1987 We are Singapore 0QeDK7Aow84hUKoLrZ1mvK
3 1990 One People, One Nation, One Singapore 0NsXuk0c78hzZkDr7UsIJ3
4 1998 Home 1vo8399T9sWFZ9vbrEcTL5
5 1999 Together 6lago1vFsu3gw26lgKGtwa
6 2000 Shine on Me 1PBxQWuUn6RFzsg30gNH0H
7 2001 Where I Belong 0u0a0p4hWefiy09bYqzZ2A
8 2002 We Will Get There 5aY2Igd9adKu3AqY1w95Xm
9 2003 One United People 2h5gMUxXk3OBfOX9KS5hiX
10 2005 Reach Out for the Skies 7phKkEWEipo3sDrZJiG9uJ
11 2006 My Island Home 2w5L5kQVkSRdduNewYPDA5
12 2007 There’s No Place I’d Rather Be 2kACPmwS9MxrNCT0vcI1nP
13 2007 Will you 2OmArKXeh9feaFzyE4UOKh
14 2008 Shine for Singapore 30QbxMta1DGgfcHUc9GfKi
15 2009 What Do You See 21gm9fNWcgpWyPY3a9t7FZ
16 2010 Song for Singapore 3S19ddIcYfyYhw7ZwKm58w
17 2011 In a Heartbeat 14dThbrteRM57dxmpV26a8
18 2012 Love at First Light 1W5ss3pBJ3W0v8gPhbLl8C
19 2013 One Singapore 4i0uKI1dwo2KEzLhsF8CWr
20 2015 Our Singapore 5WtMlbTDNZlbN8xZ5zfXva
21 2016 Tomorrow's Here Today 6cHJBXRYMS2vCPeO2IaSKY
22 2018 We are Singapore (remix) 0pSehMgUmj6t3ILbwDynI3
23 2019 Our Singapore (remix) 3UDb3MiDrkUPLMvKBWy0Sn
In [5]:
song_ids = list(origin_df['spotify_id'])
song_ids
Out[5]:
['2aIkiuxUesXTGU756fBJYD',
 '3dY7P7YoGU0gYMmFs1krC1',
 '0QeDK7Aow84hUKoLrZ1mvK',
 '0NsXuk0c78hzZkDr7UsIJ3',
 '1vo8399T9sWFZ9vbrEcTL5',
 '6lago1vFsu3gw26lgKGtwa',
 '1PBxQWuUn6RFzsg30gNH0H',
 '0u0a0p4hWefiy09bYqzZ2A',
 '5aY2Igd9adKu3AqY1w95Xm',
 '2h5gMUxXk3OBfOX9KS5hiX',
 '7phKkEWEipo3sDrZJiG9uJ',
 '2w5L5kQVkSRdduNewYPDA5',
 '2kACPmwS9MxrNCT0vcI1nP',
 '2OmArKXeh9feaFzyE4UOKh',
 '30QbxMta1DGgfcHUc9GfKi',
 '21gm9fNWcgpWyPY3a9t7FZ',
 '3S19ddIcYfyYhw7ZwKm58w',
 '14dThbrteRM57dxmpV26a8',
 '1W5ss3pBJ3W0v8gPhbLl8C',
 '4i0uKI1dwo2KEzLhsF8CWr',
 '5WtMlbTDNZlbN8xZ5zfXva',
 '6cHJBXRYMS2vCPeO2IaSKY',
 '0pSehMgUmj6t3ILbwDynI3',
 '3UDb3MiDrkUPLMvKBWy0Sn']

Get popularity index for all tracks

In [6]:
all_track_popularity = []
for song_id in song_ids:
    result = spotify.track(song_id)
    all_track_popularity.append(result['popularity'])

    
popularity_df = pd.DataFrame({'popularity': list(all_track_popularity)})
popularity_df.columns = ['popularity']
popularity_df

pd.concat([origin_df.year, origin_df.title, popularity_df], axis=1, sort=False)
Out[6]:
year title popularity
0 1985 Stand Up for Singapore 21
1 1986 Count on Me, Singapore 21
2 1987 We are Singapore 15
3 1990 One People, One Nation, One Singapore 21
4 1998 Home 30
5 1999 Together 20
6 2000 Shine on Me 13
7 2001 Where I Belong 27
8 2002 We Will Get There 16
9 2003 One United People 23
10 2005 Reach Out for the Skies 25
11 2006 My Island Home 22
12 2007 There’s No Place I’d Rather Be 17
13 2007 Will you 15
14 2008 Shine for Singapore 15
15 2009 What Do You See 20
16 2010 Song for Singapore 22
17 2011 In a Heartbeat 22
18 2012 Love at First Light 18
19 2013 One Singapore 20
20 2015 Our Singapore 25
21 2016 Tomorrow's Here Today 24
22 2018 We are Singapore (remix) 32
23 2019 Our Singapore (remix) 31

Get audio features for all songs¶

In [8]:
all_audio_features = []
for song_id in origin_df['spotify_id']:
    result = spotify.audio_features([song_id])[0]
    all_audio_features.append(result)
all_audio_features_df = pd.DataFrame(all_audio_features)
pd.concat([origin_df.year, origin_df.title, all_audio_features_df], axis=1, sort=False)
Out[8]:
year title acousticness analysis_url danceability duration_ms energy id instrumentalness key liveness loudness mode speechiness tempo time_signature track_href type uri valence
0 1985 Stand Up for Singapore 0.00122 https://api.spotify.com/v1/audio-analysis/2aIk... 0.278 116040 0.721 2aIkiuxUesXTGU756fBJYD 0.000861 0 0.4610 -4.834 1 0.0364 148.052 4 https://api.spotify.com/v1/tracks/2aIkiuxUesXT... audio_features spotify:track:2aIkiuxUesXTGU756fBJYD 0.355
1 1986 Count on Me, Singapore 0.39800 https://api.spotify.com/v1/audio-analysis/3dY7... 0.404 252987 0.614 3dY7P7YoGU0gYMmFs1krC1 0.000047 5 0.4600 -5.559 1 0.0290 85.744 4 https://api.spotify.com/v1/tracks/3dY7P7YoGU0g... audio_features spotify:track:3dY7P7YoGU0gYMmFs1krC1 0.357
2 1987 We are Singapore 0.78500 https://api.spotify.com/v1/audio-analysis/0QeD... 0.478 262966 0.545 0QeDK7Aow84hUKoLrZ1mvK 0.000026 0 0.5360 -6.408 1 0.0286 92.521 4 https://api.spotify.com/v1/tracks/0QeDK7Aow84h... audio_features spotify:track:0QeDK7Aow84hUKoLrZ1mvK 0.374
3 1990 One People, One Nation, One Singapore 0.05270 https://api.spotify.com/v1/audio-analysis/0NsX... 0.481 169813 0.524 0NsXuk0c78hzZkDr7UsIJ3 0.000000 0 0.0937 -6.987 1 0.0273 82.915 4 https://api.spotify.com/v1/tracks/0NsXuk0c78hz... audio_features spotify:track:0NsXuk0c78hzZkDr7UsIJ3 0.291
4 1998 Home 0.70200 https://api.spotify.com/v1/audio-analysis/1vo8... 0.372 254520 0.328 1vo8399T9sWFZ9vbrEcTL5 0.000000 10 0.1420 -8.418 1 0.0305 128.837 4 https://api.spotify.com/v1/tracks/1vo8399T9sWF... audio_features spotify:track:1vo8399T9sWFZ9vbrEcTL5 0.122
5 1999 Together 0.65600 https://api.spotify.com/v1/audio-analysis/6lag... 0.358 210520 0.821 6lago1vFsu3gw26lgKGtwa 0.000022 5 0.0661 -5.575 1 0.0519 79.779 4 https://api.spotify.com/v1/tracks/6lago1vFsu3g... audio_features spotify:track:6lago1vFsu3gw26lgKGtwa 0.522
6 2000 Shine on Me 0.53100 https://api.spotify.com/v1/audio-analysis/1PBx... 0.583 236680 0.484 1PBxQWuUn6RFzsg30gNH0H 0.000000 10 0.1160 -7.269 1 0.0326 121.905 4 https://api.spotify.com/v1/tracks/1PBxQWuUn6RF... audio_features spotify:track:1PBxQWuUn6RFzsg30gNH0H 0.335
7 2001 Where I Belong 0.10300 https://api.spotify.com/v1/audio-analysis/0u0a... 0.487 183160 0.510 0u0a0p4hWefiy09bYqzZ2A 0.000000 3 0.0819 -6.800 1 0.0276 109.155 4 https://api.spotify.com/v1/tracks/0u0a0p4hWefi... audio_features spotify:track:0u0a0p4hWefiy09bYqzZ2A 0.105
8 2002 We Will Get There 0.06950 https://api.spotify.com/v1/audio-analysis/5aY2... 0.607 249107 0.795 5aY2Igd9adKu3AqY1w95Xm 0.000004 8 0.1410 -5.836 1 0.0379 119.973 4 https://api.spotify.com/v1/tracks/5aY2Igd9adKu... audio_features spotify:track:5aY2Igd9adKu3AqY1w95Xm 0.323
9 2003 One United People 0.35000 https://api.spotify.com/v1/audio-analysis/2h5g... 0.488 171320 0.760 2h5gMUxXk3OBfOX9KS5hiX 0.000000 11 0.3580 -5.850 1 0.0381 79.962 4 https://api.spotify.com/v1/tracks/2h5gMUxXk3OB... audio_features spotify:track:2h5gMUxXk3OBfOX9KS5hiX 0.501
10 2005 Reach Out for the Skies 0.11700 https://api.spotify.com/v1/audio-analysis/7phK... 0.497 174827 0.861 7phKkEWEipo3sDrZJiG9uJ 0.000000 4 0.3370 -5.556 1 0.0639 127.989 4 https://api.spotify.com/v1/tracks/7phKkEWEipo3... audio_features spotify:track:7phKkEWEipo3sDrZJiG9uJ 0.577
11 2006 My Island Home 0.13400 https://api.spotify.com/v1/audio-analysis/2w5L... 0.450 184120 0.782 2w5L5kQVkSRdduNewYPDA5 0.000000 0 0.0632 -5.905 1 0.0306 87.980 4 https://api.spotify.com/v1/tracks/2w5L5kQVkSRd... audio_features spotify:track:2w5L5kQVkSRdduNewYPDA5 0.475
12 2007 There’s No Place I’d Rather Be 0.60100 https://api.spotify.com/v1/audio-analysis/2kAC... 0.323 183093 0.342 2kACPmwS9MxrNCT0vcI1nP 0.000006 5 0.1150 -7.795 1 0.0331 139.563 3 https://api.spotify.com/v1/tracks/2kACPmwS9Mxr... audio_features spotify:track:2kACPmwS9MxrNCT0vcI1nP 0.199
13 2007 Will you 0.26900 https://api.spotify.com/v1/audio-analysis/2OmA... 0.551 183587 0.896 2OmArKXeh9feaFzyE4UOKh 0.000000 8 0.3500 -5.385 1 0.2230 131.931 4 https://api.spotify.com/v1/tracks/2OmArKXeh9fe... audio_features spotify:track:2OmArKXeh9feaFzyE4UOKh 0.418
14 2008 Shine for Singapore 0.43000 https://api.spotify.com/v1/audio-analysis/30Qb... 0.231 180733 0.745 30QbxMta1DGgfcHUc9GfKi 0.000001 4 0.3910 -4.506 1 0.0456 85.151 1 https://api.spotify.com/v1/tracks/30QbxMta1DGg... audio_features spotify:track:30QbxMta1DGgfcHUc9GfKi 0.366
15 2009 What Do You See 0.04630 https://api.spotify.com/v1/audio-analysis/21gm... 0.426 237140 0.733 21gm9fNWcgpWyPY3a9t7FZ 0.000415 4 0.3640 -5.933 1 0.0437 136.893 4 https://api.spotify.com/v1/tracks/21gm9fNWcgpW... audio_features spotify:track:21gm9fNWcgpWyPY3a9t7FZ 0.260
16 2010 Song for Singapore 0.33600 https://api.spotify.com/v1/audio-analysis/3S19... 0.557 213693 0.440 3S19ddIcYfyYhw7ZwKm58w 0.000000 7 0.1010 -7.991 1 0.0290 136.097 4 https://api.spotify.com/v1/tracks/3S19ddIcYfyY... audio_features spotify:track:3S19ddIcYfyYhw7ZwKm58w 0.141
17 2011 In a Heartbeat 0.59300 https://api.spotify.com/v1/audio-analysis/14dT... 0.388 242640 0.461 14dThbrteRM57dxmpV26a8 0.000000 9 0.1040 -6.383 1 0.0272 165.616 4 https://api.spotify.com/v1/tracks/14dThbrteRM5... audio_features spotify:track:14dThbrteRM57dxmpV26a8 0.187
18 2012 Love at First Light 0.74800 https://api.spotify.com/v1/audio-analysis/1W5s... 0.526 222827 0.544 1W5ss3pBJ3W0v8gPhbLl8C 0.000000 3 0.1530 -5.172 1 0.0398 74.026 4 https://api.spotify.com/v1/tracks/1W5ss3pBJ3W0... audio_features spotify:track:1W5ss3pBJ3W0v8gPhbLl8C 0.276
19 2013 One Singapore 0.91800 https://api.spotify.com/v1/audio-analysis/4i0u... 0.598 222000 0.261 4i0uKI1dwo2KEzLhsF8CWr 0.000177 5 0.1380 -11.090 1 0.0297 100.003 4 https://api.spotify.com/v1/tracks/4i0uKI1dwo2K... audio_features spotify:track:4i0uKI1dwo2KEzLhsF8CWr 0.238
20 2015 Our Singapore 0.39300 https://api.spotify.com/v1/audio-analysis/5WtM... 0.564 208587 0.500 5WtMlbTDNZlbN8xZ5zfXva 0.000000 7 0.1220 -8.291 1 0.0354 107.220 4 https://api.spotify.com/v1/tracks/5WtMlbTDNZlb... audio_features spotify:track:5WtMlbTDNZlbN8xZ5zfXva 0.311
21 2016 Tomorrow's Here Today 0.08290 https://api.spotify.com/v1/audio-analysis/6cHJ... 0.692 202511 0.779 6cHJBXRYMS2vCPeO2IaSKY 0.000000 4 0.3800 -6.886 1 0.0439 129.057 4 https://api.spotify.com/v1/tracks/6cHJBXRYMS2v... audio_features spotify:track:6cHJBXRYMS2vCPeO2IaSKY 0.792
22 2018 We are Singapore (remix) 0.72800 https://api.spotify.com/v1/audio-analysis/0pSe... 0.675 215916 0.379 0pSehMgUmj6t3ILbwDynI3 0.000000 3 0.1520 -10.436 1 0.0435 91.973 4 https://api.spotify.com/v1/tracks/0pSehMgUmj6t... audio_features spotify:track:0pSehMgUmj6t3ILbwDynI3 0.410
23 2019 Our Singapore (remix) 0.79700 https://api.spotify.com/v1/audio-analysis/3UDb... 0.430 240419 0.264 3UDb3MiDrkUPLMvKBWy0Sn 0.000006 2 0.3260 -15.309 1 0.0630 104.083 4 https://api.spotify.com/v1/tracks/3UDb3MiDrkUP... audio_features spotify:track:3UDb3MiDrkUPLMvKBWy0Sn 0.286

Extract features and normalization

Audio Features Object - Spoity API

  • Danceability: Danceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.
  • Acousticness: A measure from 0.0 to 1.0 of whether the track is acoustic.
  • Energy: Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. Instrumentalness: Predicts whether a track contains no vocals. The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content.
  • Liveness: Detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live.
  • Loudness: The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track. Values typical range between -60 and 0 db. Speechiness: Speechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value.
  • Tempo: The overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.
  • Valence: A measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).
In [12]:
features_keys = ['loudness', 'acousticness', 'duration_ms', 'energy', 'speechiness', 'acousticness', 'liveness', 'danceability', 'valence', 'key', 'tempo']

# Get list of features and normalize values from 0 to 1
# In order to plot, normalize the key, loudness, tempo, and duration_ms values to be from 0 to 1. 
def normalized(key, lst):
    feature = [x[key] for x in lst]
    if key in features_keys:
        return list(minmax_scale(feature))
    else:
        return feature
    
audio_features_res = {}
for key in features_keys:
    audio_features_res[key] = normalized(key, all_audio_features)
    

audio_features_df = pd.DataFrame(audio_features_res)
audio_features_df.rename(columns={'duration_ms':'duration'}, inplace=True)
audio_features_df
Out[12]:
loudness acousticness duration energy speechiness liveness danceability valence key tempo
0 0.969638 0.000000 0.000000 0.724409 0.046987 0.841371 0.101952 0.363901 0.000000 0.808232
1 0.902527 0.432797 0.932081 0.555906 0.009193 0.839255 0.375271 0.366812 0.454545 0.127940
2 0.823938 0.854927 1.000000 0.447244 0.007150 1.000000 0.535792 0.391557 0.000000 0.201933
3 0.770342 0.056153 0.365987 0.414173 0.000511 0.064509 0.542299 0.270742 0.000000 0.097052
4 0.637878 0.764393 0.942515 0.105512 0.016854 0.166667 0.305857 0.024745 0.909091 0.598439
5 0.901046 0.714217 0.643045 0.881890 0.126149 0.006134 0.275488 0.606987 0.454545 0.062813
6 0.744238 0.577870 0.821094 0.351181 0.027579 0.111675 0.763557 0.334789 0.909091 0.522754
7 0.787652 0.111019 0.456829 0.392126 0.002043 0.039552 0.555315 0.000000 0.272727 0.383546
8 0.876886 0.074478 0.905674 0.840945 0.054648 0.164552 0.815618 0.317322 0.727273 0.501660
9 0.875590 0.380440 0.376244 0.785827 0.055669 0.623519 0.557484 0.576419 1.000000 0.064811
10 0.902805 0.126290 0.400113 0.944882 0.187436 0.579103 0.577007 0.687045 0.363636 0.589180
11 0.870499 0.144833 0.463363 0.820472 0.017365 0.000000 0.475054 0.538574 0.000000 0.152353
12 0.695548 0.654225 0.456373 0.127559 0.030133 0.109560 0.199566 0.136827 0.454545 0.715548
13 0.918634 0.292088 0.459735 1.000000 1.000000 0.606599 0.694143 0.455604 0.727273 0.632220
14 1.000000 0.467702 0.440310 0.762205 0.093973 0.693316 0.000000 0.379913 0.363636 0.121465
15 0.867907 0.049172 0.824224 0.743307 0.084270 0.636210 0.422993 0.225619 0.363636 0.686396
16 0.677404 0.365169 0.664641 0.281890 0.009193 0.079949 0.707158 0.052402 0.636364 0.677705
17 0.826252 0.645498 0.861658 0.314961 0.000000 0.086294 0.340564 0.119360 0.818182 1.000000
18 0.938350 0.814568 0.726808 0.445669 0.064351 0.189932 0.639913 0.248908 0.272727 0.000000
19 0.390540 1.000000 0.721179 0.000000 0.012768 0.158206 0.796095 0.193595 0.454545 0.283623
20 0.649634 0.427344 0.629889 0.376378 0.041879 0.124365 0.722343 0.299854 0.636364 0.362419
21 0.779691 0.089094 0.588534 0.815748 0.085291 0.670051 1.000000 1.000000 0.363636 0.600841
22 0.451078 0.792753 0.679771 0.185827 0.083248 0.187817 0.963124 0.443959 0.272727 0.195949
23 0.000000 0.868016 0.846542 0.004724 0.182840 0.555838 0.431670 0.263464 0.181818 0.328169

Make audio features visualization - Radar Chart

In [14]:
radar_chart_df = pd.concat([origin_df.year, origin_df.title, audio_features_df], axis=1, sort=False)
radar_chart_df
Out[14]:
year title loudness acousticness duration energy speechiness liveness danceability valence key tempo
0 1985 Stand Up for Singapore 0.969638 0.000000 0.000000 0.724409 0.046987 0.841371 0.101952 0.363901 0.000000 0.808232
1 1986 Count on Me, Singapore 0.902527 0.432797 0.932081 0.555906 0.009193 0.839255 0.375271 0.366812 0.454545 0.127940
2 1987 We are Singapore 0.823938 0.854927 1.000000 0.447244 0.007150 1.000000 0.535792 0.391557 0.000000 0.201933
3 1990 One People, One Nation, One Singapore 0.770342 0.056153 0.365987 0.414173 0.000511 0.064509 0.542299 0.270742 0.000000 0.097052
4 1998 Home 0.637878 0.764393 0.942515 0.105512 0.016854 0.166667 0.305857 0.024745 0.909091 0.598439
5 1999 Together 0.901046 0.714217 0.643045 0.881890 0.126149 0.006134 0.275488 0.606987 0.454545 0.062813
6 2000 Shine on Me 0.744238 0.577870 0.821094 0.351181 0.027579 0.111675 0.763557 0.334789 0.909091 0.522754
7 2001 Where I Belong 0.787652 0.111019 0.456829 0.392126 0.002043 0.039552 0.555315 0.000000 0.272727 0.383546
8 2002 We Will Get There 0.876886 0.074478 0.905674 0.840945 0.054648 0.164552 0.815618 0.317322 0.727273 0.501660
9 2003 One United People 0.875590 0.380440 0.376244 0.785827 0.055669 0.623519 0.557484 0.576419 1.000000 0.064811
10 2005 Reach Out for the Skies 0.902805 0.126290 0.400113 0.944882 0.187436 0.579103 0.577007 0.687045 0.363636 0.589180
11 2006 My Island Home 0.870499 0.144833 0.463363 0.820472 0.017365 0.000000 0.475054 0.538574 0.000000 0.152353
12 2007 There’s No Place I’d Rather Be 0.695548 0.654225 0.456373 0.127559 0.030133 0.109560 0.199566 0.136827 0.454545 0.715548
13 2007 Will you 0.918634 0.292088 0.459735 1.000000 1.000000 0.606599 0.694143 0.455604 0.727273 0.632220
14 2008 Shine for Singapore 1.000000 0.467702 0.440310 0.762205 0.093973 0.693316 0.000000 0.379913 0.363636 0.121465
15 2009 What Do You See 0.867907 0.049172 0.824224 0.743307 0.084270 0.636210 0.422993 0.225619 0.363636 0.686396
16 2010 Song for Singapore 0.677404 0.365169 0.664641 0.281890 0.009193 0.079949 0.707158 0.052402 0.636364 0.677705
17 2011 In a Heartbeat 0.826252 0.645498 0.861658 0.314961 0.000000 0.086294 0.340564 0.119360 0.818182 1.000000
18 2012 Love at First Light 0.938350 0.814568 0.726808 0.445669 0.064351 0.189932 0.639913 0.248908 0.272727 0.000000
19 2013 One Singapore 0.390540 1.000000 0.721179 0.000000 0.012768 0.158206 0.796095 0.193595 0.454545 0.283623
20 2015 Our Singapore 0.649634 0.427344 0.629889 0.376378 0.041879 0.124365 0.722343 0.299854 0.636364 0.362419
21 2016 Tomorrow's Here Today 0.779691 0.089094 0.588534 0.815748 0.085291 0.670051 1.000000 1.000000 0.363636 0.600841
22 2018 We are Singapore (remix) 0.451078 0.792753 0.679771 0.185827 0.083248 0.187817 0.963124 0.443959 0.272727 0.195949
23 2019 Our Singapore (remix) 0.000000 0.868016 0.846542 0.004724 0.182840 0.555838 0.431670 0.263464 0.181818 0.328169
In [15]:
# Set font
FONT_NAME = "Hack Nerd Font"
plt.rcParams['font.family'] = FONT_NAME
plt.rcParams['axes.unicode_minus'] = False
df = radar_chart_df

SONG_YEARS = origin_df['year']
SONG_TITLES = origin_df['title']

# List all fonts available in matplotlib plus samples
# http://jonathansoma.com/lede/foundations-2018/matplotlib/list-all-fonts-available-in-matplotlib-plus-samples/

def make_spider(row, title, color):
     
# number of variable
    categories=list(df)[2:]
    N = len(categories)
    # What will be the angle of each axis in the plot? (we divide the plot / number of variable)
    angles = [n / float(N) * 2 * pi for n in range(N)]
    angles += angles[:1]

    # Initialise the spider plot
    ax = plt.subplot(10,3,row+1, polar=True)
    # If you want the first axis to be on top:
    ax.set_theta_offset(pi / 2)
    ax.set_theta_direction(-1)

    # Draw one axe per variable + add labels labels yet
    plt.xticks(angles[:-1], categories, color='grey', size=8)
    ax.tick_params(axis='both', which='major', pad=15)

    # Draw ylabels
    ax.set_rlabel_position(0)
    plt.yticks([0.0, 0.5, 1], ["0.0","0.5", "1"], color="grey", size=7)
    plt.ylim(0,1)
    
    
    # Set starting index
    values=df.iloc[row].tolist()[2:]
    values += values[:1]
    ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
    ax.fill(angles, values, color=color, alpha=0.4)

    # Add a title
    plt.title(title, size=11, color=color, y=1.2)

# initialize the figure
my_dpi=100
plt.figure(figsize=(1500/my_dpi, 4000/my_dpi), dpi=my_dpi)
plt.subplots_adjust(hspace = .8)
plt.suptitle(f'NDP SONGS - Spotify Audio Features Analysis', y=.95, fontsize=16, va='center')

# Create a color palette
my_palette = plt.cm.get_cmap("tab10") 

# Loop to plot
for row in range(0, len(df.index)):
    make_spider(row=row, title=f'({SONG_YEARS[row]}) {SONG_TITLES[row]}', color=my_palette(int(row/3)))

if not os.path.exists('image'):
    os.makedirs('image')

plt.savefig(f'image/ndp-songs-spotify.png', dpi=300)
plt.show()
plt.close()
In [ ]: