Using Spotify Api
api pandas matplotlib
Exploring Spotify’s Emotional Measurements
This is my first Python project that involves API calling, Pandas manipulation, and visualizations accompanying the analysis. Below is the full notebook. I download the weekly charts data from charts.spotify.com, as well as the last year of my listening data from Spotify (at the time of 4/21/22). My recent switch to Apple Music means I have a whole account of data to analyze, so I want to continue exploring Spotify’s emotional data with journal posts in the future.
Notebook
For my final project, I aimed to answer the question: “Do my listening habits differ from others in terms of emotion?” After exploring the data, my question shifted to: “How does the Spotify emotional data of my personal listening history compare to the top 10 songs during the week of 4/21/22?” I also sought to answer some other questions related to the measurement of emotional data. These questions are: “Does an increase in tempo mean an increase in valence?” and “Does an increase in tempo mean an increase in danceability?”. Spotify gathers an immense amount of data regarding a song’s musical information, such as tempo, key, timbre, and various other measurements to compute the track’s valence. According to Spotify, valence is defined as “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)”. I wanted to use this value to compare my music to others, and to assess how strong a song’s tempo can be in a song measurement.
As someone who listens to heavier music year-round, I am curious to put both my and the listening chart's top 10 tracks side by side and examine each track's emotional data that spotify measures. To do this, I must begin by accessing Spotify's API.
The below code is the spotifyAPIExample available on Canvas. I used this to setup the spotify api requests.
import requests
clientID = "[REDACTED] # your client ID here
clientSecret = "[REDACTED] # your client secret here
grantType = 'client_credentials'
#Request based on Client Credentials Flow from https://developer.spotify.com/web-api/authorization-guide/
#Request body parameter: grant_type Value: Required. Set it to client_credentials
bodyParams = {'grant_type' : grantType}
url='https://accounts.spotify.com/api/token'
response=requests.post(url, data=bodyParams, auth = (clientID, clientSecret)).json()
# print (response) # this response should be a json object (dictionary) with an access_token key. # you'll need
# the access token key in subsequent calls. you can access it using response["access_token"]
headers = {"Authorization": "Bearer "+response["access_token"]} # you'll use this in your subsequent requests
# example request
mastodonSearch=requests.get("https://api.spotify.com/v1/search?q=Mastodon&type=artist", headers=headers).json()
mastodonSearch
{'artists': {'href': 'https://api.spotify.com/v1/search?query=Mastodon&type=artist&offset=0&limit=20', 'items': [{'external_urls': {'spotify': 'https://open.spotify.com/artist/1Dvfqq39HxvCJ3GvfeIFuT'}, 'followers': {'href': None, 'total': 730175}, 'genres': ['alternative metal', 'atlanta metal', 'hard rock', 'metal', 'nu metal', 'progressive groove metal', 'progressive sludge', 'rock', 'sludge metal', 'stoner metal'], 'href': 'https://api.spotify.com/v1/artists/1Dvfqq39HxvCJ3GvfeIFuT', 'id': '1Dvfqq39HxvCJ3GvfeIFuT', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab6761610000e5ebf84fe9e6fbb2aa001d6cbbd9', 'width': 640}, {'height': 320, 'url': 'https://i.scdn.co/image/ab67616100005174f84fe9e6fbb2aa001d6cbbd9', 'width': 320}, {'height': 160, 'url': 'https://i.scdn.co/image/ab6761610000f178f84fe9e6fbb2aa001d6cbbd9', 'width': 160}], 'name': 'Mastodon', 'popularity': 63, 'type': 'artist', 'uri': 'spotify:artist:1Dvfqq39HxvCJ3GvfeIFuT'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/4hXAEP4eZ8Et0UMdOdOf0E'}, 'followers': {'href': None, 'total': 7765}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/4hXAEP4eZ8Et0UMdOdOf0E', 'id': '4hXAEP4eZ8Et0UMdOdOf0E', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab6761610000e5eb706441b97a9d9521bed90a19', 'width': 640}, {'height': 320, 'url': 'https://i.scdn.co/image/ab67616100005174706441b97a9d9521bed90a19', 'width': 320}, {'height': 160, 'url': 'https://i.scdn.co/image/ab6761610000f178706441b97a9d9521bed90a19', 'width': 160}], 'name': 'Mastodonte', 'popularity': 25, 'type': 'artist', 'uri': 'spotify:artist:4hXAEP4eZ8Et0UMdOdOf0E'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/4QHrnzMEIo0VgOUJSJZwTN'}, 'followers': {'href': None, 'total': 320}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/4QHrnzMEIo0VgOUJSJZwTN', 'id': '4QHrnzMEIo0VgOUJSJZwTN', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab6761610000e5eb1d337b9058066f95ef07062b', 'width': 640}, {'height': 320, 'url': 'https://i.scdn.co/image/ab676161000051741d337b9058066f95ef07062b', 'width': 320}, {'height': 160, 'url': 'https://i.scdn.co/image/ab6761610000f1781d337b9058066f95ef07062b', 'width': 160}], 'name': 'MastodonRare', 'popularity': 1, 'type': 'artist', 'uri': 'spotify:artist:4QHrnzMEIo0VgOUJSJZwTN'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/1UtrqakmT1FJgaClaFtejp'}, 'followers': {'href': None, 'total': 0}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/1UtrqakmT1FJgaClaFtejp', 'id': '1UtrqakmT1FJgaClaFtejp', 'images': [], 'name': 'mastodonte', 'popularity': 0, 'type': 'artist', 'uri': 'spotify:artist:1UtrqakmT1FJgaClaFtejp'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/3wnSv5NhMXhqMbXwzPVpn2'}, 'followers': {'href': None, 'total': 38}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/3wnSv5NhMXhqMbXwzPVpn2', 'id': '3wnSv5NhMXhqMbXwzPVpn2', 'images': [], 'name': 'Mastodonterne', 'popularity': 6, 'type': 'artist', 'uri': 'spotify:artist:3wnSv5NhMXhqMbXwzPVpn2'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/0qxJCNIBMG8pxsRyvGeXFc'}, 'followers': {'href': None, 'total': 1}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/0qxJCNIBMG8pxsRyvGeXFc', 'id': '0qxJCNIBMG8pxsRyvGeXFc', 'images': [], 'name': 'Mastodonte', 'popularity': 0, 'type': 'artist', 'uri': 'spotify:artist:0qxJCNIBMG8pxsRyvGeXFc'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/484ogm5RWziRLqXjiOI4Ll'}, 'followers': {'href': None, 'total': 108}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/484ogm5RWziRLqXjiOI4Ll', 'id': '484ogm5RWziRLqXjiOI4Ll', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab6761610000e5ebc61780f91fcd7cda00555210', 'width': 640}, {'height': 320, 'url': 'https://i.scdn.co/image/ab67616100005174c61780f91fcd7cda00555210', 'width': 320}, {'height': 160, 'url': 'https://i.scdn.co/image/ab6761610000f178c61780f91fcd7cda00555210', 'width': 160}], 'name': 'Mastodonte', 'popularity': 0, 'type': 'artist', 'uri': 'spotify:artist:484ogm5RWziRLqXjiOI4Ll'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/5ZD2iBgKuBsL2o1dy1uXyj'}, 'followers': {'href': None, 'total': 0}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/5ZD2iBgKuBsL2o1dy1uXyj', 'id': '5ZD2iBgKuBsL2o1dy1uXyj', 'images': [], 'name': 'Mastodonrare', 'popularity': 0, 'type': 'artist', 'uri': 'spotify:artist:5ZD2iBgKuBsL2o1dy1uXyj'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/6shD5eNBVTdksVEt55PLTx'}, 'followers': {'href': None, 'total': 202}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/6shD5eNBVTdksVEt55PLTx', 'id': '6shD5eNBVTdksVEt55PLTx', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab6761610000e5eb8794e2e0c4f1edcb58a2a2bf', 'width': 640}, {'height': 320, 'url': 'https://i.scdn.co/image/ab676161000051748794e2e0c4f1edcb58a2a2bf', 'width': 320}, {'height': 160, 'url': 'https://i.scdn.co/image/ab6761610000f1788794e2e0c4f1edcb58a2a2bf', 'width': 160}], 'name': 'Mastodonte', 'popularity': 2, 'type': 'artist', 'uri': 'spotify:artist:6shD5eNBVTdksVEt55PLTx'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/6ujkhtKxBfEN3CQvVqIgaW'}, 'followers': {'href': None, 'total': 2}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/6ujkhtKxBfEN3CQvVqIgaW', 'id': '6ujkhtKxBfEN3CQvVqIgaW', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab67616d0000b2732f273ab84a8699e17f2d8a98', 'width': 640}, {'height': 300, 'url': 'https://i.scdn.co/image/ab67616d00001e022f273ab84a8699e17f2d8a98', 'width': 300}, {'height': 64, 'url': 'https://i.scdn.co/image/ab67616d000048512f273ab84a8699e17f2d8a98', 'width': 64}], 'name': 'Mastodonte', 'popularity': 0, 'type': 'artist', 'uri': 'spotify:artist:6ujkhtKxBfEN3CQvVqIgaW'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/4yQwkGertP7mvkpuhHkjD8'}, 'followers': {'href': None, 'total': 0}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/4yQwkGertP7mvkpuhHkjD8', 'id': '4yQwkGertP7mvkpuhHkjD8', 'images': [], 'name': 'Mastodonte', 'popularity': 0, 'type': 'artist', 'uri': 'spotify:artist:4yQwkGertP7mvkpuhHkjD8'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/7qyoqpwK4ALbvJ33jJbyIN'}, 'followers': {'href': None, 'total': 1320}, 'genres': ['musica popular paraense'], 'href': 'https://api.spotify.com/v1/artists/7qyoqpwK4ALbvJ33jJbyIN', 'id': '7qyoqpwK4ALbvJ33jJbyIN', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab6761610000e5eb91ed889f1b978bcb5d19aec1', 'width': 640}, {'height': 320, 'url': 'https://i.scdn.co/image/ab6761610000517491ed889f1b978bcb5d19aec1', 'width': 320}, {'height': 160, 'url': 'https://i.scdn.co/image/ab6761610000f17891ed889f1b978bcb5d19aec1', 'width': 160}], 'name': 'Bando Mastodontes', 'popularity': 14, 'type': 'artist', 'uri': 'spotify:artist:7qyoqpwK4ALbvJ33jJbyIN'}, {'external_urls': {'spotify': 'https://open.spotify.com/artist/7Fhp9FkCur0n6MeXGFlCU1'}, 'followers': {'href': None, 'total': 2}, 'genres': [], 'href': 'https://api.spotify.com/v1/artists/7Fhp9FkCur0n6MeXGFlCU1', 'id': '7Fhp9FkCur0n6MeXGFlCU1', 'images': [{'height': 640, 'url': 'https://i.scdn.co/image/ab67616d0000b273e76678d552d50bf3a6547312', 'width': 640}, {'height': 300, 'url': 'https://i.scdn.co/image/ab67616d00001e02e76678d552d50bf3a6547312', 'width': 300}, {'height': 64, 'url': 'https://i.scdn.co/image/ab67616d00004851e76678d552d50bf3a6547312', 'width': 64}], 'name': 'Dblackz MastoDon', 'popularity': 0, 'type': 'artist', 'uri': 'spotify:artist:7Fhp9FkCur0n6MeXGFlCU1'}], 'limit': 20, 'next': None, 'offset': 0, 'previous': None, 'total': 13}}
Now that we can access the API, we must gather the specific Song ID from the top tracks of the current week (4/21/22). For this data, I will be downloading the CSV available at spotifycharts.com. Here is a preview of the CSV.
import pandas as pd
import numpy as np
chartsPreview = pd.read_csv("TOPCHARTS.CSV", header=None)
#creates dataframe from the csv
chartsPreview.head(5)
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | NaN | NaN | NaN | Note that these figures are generated using a ... | NaN |
1 | Position | Track Name | Artist | Streams | URL |
2 | 1 | As It Was | Harry Styles | 67265741 | https://open.spotify.com/track/4LRPiXqCikLlN15... |
3 | 2 | First Class | Jack Harlow | 50438229 | https://open.spotify.com/track/1rDQ4oMwGJI7B4t... |
4 | 3 | Heat Waves | Glass Animals | 29307788 | https://open.spotify.com/track/02MWAaffLxlfxAU... |
To gather song data using the API, we must extract the unique song IDs from the dataframe. To do this, we will create a series object of the song IDs, then convert it into a list.
songID = chartsPreview[4] # creates a series object of the track URL column
print(type(songID))
songID
<class 'pandas.core.series.Series'>
0 NaN 1 URL 2 https://open.spotify.com/track/4LRPiXqCikLlN15... 3 https://open.spotify.com/track/1rDQ4oMwGJI7B4t... 4 https://open.spotify.com/track/02MWAaffLxlfxAU... ... 197 https://open.spotify.com/track/0B7wvvmu9EISAwZ... 198 https://open.spotify.com/track/3rq5w4bQGigXOfd... 199 https://open.spotify.com/track/285pBltuF7vW8Te... 200 https://open.spotify.com/track/2BEcap3xJtmiPaH... 201 https://open.spotify.com/track/2VxeLyX666F8uXC... Name: 4, Length: 202, dtype: object
songIDList = songID.to_list() # turns the series object into a list
print(songIDList)
[nan, 'URL', 'https://open.spotify.com/track/4LRPiXqCikLlN15c3yImP7', 'https://open.spotify.com/track/1rDQ4oMwGJI7B4tovsBOxc', 'https://open.spotify.com/track/02MWAaffLxlfxAUY7c5dvx', 'https://open.spotify.com/track/5PjdY0CKGZdEuoNab3yDmX', 'https://open.spotify.com/track/1HhNoOuqm1a5MXYEgAFl8o', 'https://open.spotify.com/track/3FkeNbs9Zeiqkr3WkbOiGp', 'https://open.spotify.com/track/2DB4DdfCFMw1iaR6JaR03a', 'https://open.spotify.com/track/5Z9KJZvQzH6PFmb8SNkxuk', 'https://open.spotify.com/track/7rglLriMNBPAyuJOMGwi39', 'https://open.spotify.com/track/4fouWK6XVHhzl78KzQ1UjL', 'https://open.spotify.com/track/1O2pcBJGej0pmH2Y9XZMs6', 'https://open.spotify.com/track/1ri9ZUkBJVFUdgwzCnfcYs', 'https://open.spotify.com/track/6I3mqTwhRpn34SLVafSH7G', 'https://open.spotify.com/track/58HvfVOeJY7lUuCqF0m3ly', 'https://open.spotify.com/track/6mmPpaltUZK7xjNlBPQQ0p', 'https://open.spotify.com/track/2gpQi3hbcUAcEG8m2dlgfB', 'https://open.spotify.com/track/6Uj1ctrBOjOas8xZXGqKk4', 'https://open.spotify.com/track/50nfwKoDiSYg8zOCREWAm5', 'https://open.spotify.com/track/4ZtFanR9U6ndgddUvNcjcG', 'https://open.spotify.com/track/46IZ0fSY2mpAiktS3KOqds', 'https://open.spotify.com/track/0e8nrvls4Qqv5Rfa2UhqmO', 'https://open.spotify.com/track/1UdzJEpgJxtuXAlCOvD4S0', 'https://open.spotify.com/track/3uUuGVFu1V7jTQL60S1r8z', 'https://open.spotify.com/track/48AJSd42lXpicsGqcgopof', 'https://open.spotify.com/track/3rmo8F54jFF8OgYsqTxm5d', 'https://open.spotify.com/track/2B4GHvToeLTOBB4QLzW3Ni', 'https://open.spotify.com/track/18asYwWugKjjsihZ0YvRxO', 'https://open.spotify.com/track/46HNZY1i7O6jwTA7Slo2PI', 'https://open.spotify.com/track/59CfNbkERJ3NoTXDvoURjj', 'https://open.spotify.com/track/3AVXwaOGCEL8cmBecfcsFJ', 'https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b', 'https://open.spotify.com/track/0U1W2LZVUX7qTm7dDpqxh6', 'https://open.spotify.com/track/7jtQIBanIiJOMS6RyCx6jZ', 'https://open.spotify.com/track/1SOClUWhOi8vHZYMz3GluK', 'https://open.spotify.com/track/5CZ40GBx1sQ9agT82CLQCT', 'https://open.spotify.com/track/2QjOHCTQ1Jl3zawyYOpxh6', 'https://open.spotify.com/track/4gzsuuZypVbxs0Af1LSZyB', 'https://open.spotify.com/track/1HvTxgCj0mTzQlEo0zLvFb', 'https://open.spotify.com/track/3DarAbFujv6eYNliUTyqtz', 'https://open.spotify.com/track/2eAvDnpXP5W0cVtiI0PUxV', 'https://open.spotify.com/track/6UelLqGlWMcVH1E5c4H7lY', 'https://open.spotify.com/track/3Vi5XqYrmQgOYBajMWSvCi', 'https://open.spotify.com/track/5wANPM4fQCJwkGd4rN57mH', 'https://open.spotify.com/track/4SqWKzw0CbA05TGszDgMlc', 'https://open.spotify.com/track/2JPLbjOn0wPCngEot2STUS', 'https://open.spotify.com/track/0y60itmpH0aPKsFiGxmtnh', 'https://open.spotify.com/track/5nujrmhLynf4yMoMtj8AQF', 'https://open.spotify.com/track/2rDZhKnPaPG054ExZ6nXUS', 'https://open.spotify.com/track/4RVwu0g32PAqgUiJoXsdF8', 'https://open.spotify.com/track/5QO79kh1waicV47BqGRL3g', 'https://open.spotify.com/track/0Q5VnK2DYzRyfqQRJuUtvi', 'https://open.spotify.com/track/20on25jryn53hWghthWWW3', 'https://open.spotify.com/track/1oFAF1hdPOickyHgbuRjyX', 'https://open.spotify.com/track/6HU7h9RYOaPRFeh0R3UeAr', 'https://open.spotify.com/track/4srcMdbm2qzVG98tJajHxp', 'https://open.spotify.com/track/2SJZdZ5DLtlRosJ2xHJJJa', 'https://open.spotify.com/track/58ge6dfP91o9oXMzq3XkIS', 'https://open.spotify.com/track/3AJwUDP919kvQ9QcozQPxg', 'https://open.spotify.com/track/1SC5rEoYDGUK4NfG82494W', 'https://open.spotify.com/track/531KGXtBroSrOX9LVmiIgc', 'https://open.spotify.com/track/5gflgO9EPbIBf16n5TKnQS', 'https://open.spotify.com/track/7lQ8MOhq6IN2w8EYcFNSUk', 'https://open.spotify.com/track/0HqZX76SFLDz2aW8aiqi7G', 'https://open.spotify.com/track/3uwnnTQcHM1rDqSfA4gQNz', 'https://open.spotify.com/track/2K7xn816oNHJZ0aVqdQsha', 'https://open.spotify.com/track/6lX6l7OuA3qrnIRfdsr0dw', 'https://open.spotify.com/track/52xJxFP6TqMuO4Yt0eOkMz', 'https://open.spotify.com/track/4MzXwWMhyBbmu6hOcLVD49', 'https://open.spotify.com/track/62Yo3FDddWY8ydu6PW2wyz', 'https://open.spotify.com/track/1mWdTewIgB3gtBM3TOSFhB', 'https://open.spotify.com/track/73cnVqsbZygieKi8xF10sO', 'https://open.spotify.com/track/0IuVhCflrQPMGRrOyoY5RW', 'https://open.spotify.com/track/6ylDpki1VpIsc525KC1ojF', 'https://open.spotify.com/track/4iJyoBOLtHqaGxP12qzhQI', 'https://open.spotify.com/track/3GaGWoU1KfVqgl7vnRHP55', 'https://open.spotify.com/track/3Wrjm47oTz2sjIgck11l5e', 'https://open.spotify.com/track/0pqnGHJpmpxLKifKRmU6WP', 'https://open.spotify.com/track/0Bv7O6fmZk3GrNQFYJaXPn', 'https://open.spotify.com/track/5TMLavqGRKNxgzMBrVpC9R', 'https://open.spotify.com/track/0oA9wBGDY4uyILLg4GymWP', 'https://open.spotify.com/track/3yfqSUWxFvZELEM4PmlwIR', 'https://open.spotify.com/track/6bTdZ7xfKp3NqqADJ8HLyj', 'https://open.spotify.com/track/2gQPv5jvVPqU2a9HhMNO1v', 'https://open.spotify.com/track/2m6Ko3CY1qXNNja8AlugNc', 'https://open.spotify.com/track/5QDLhrAOJJdNAmCTJ8xMyW', 'https://open.spotify.com/track/6bQ5823aHmFVKLZW8E7rRo', 'https://open.spotify.com/track/02VBYrHfVwfEWXk5DXyf0T', 'https://open.spotify.com/track/2Xr1dTzJee307rmrkt8c0g', 'https://open.spotify.com/track/5zNxUkUW9WiV5oyg6gh2wB', 'https://open.spotify.com/track/3rdAz1fbUfZxYgaCviYhRo', 'https://open.spotify.com/track/7mFj0LlWtEJaEigguaWqYh', 'https://open.spotify.com/track/2WL6GQzPuK9Nrpy9XwNEbz', 'https://open.spotify.com/track/4r9jkMEnArtWGH2rL2FZl0', 'https://open.spotify.com/track/3PfIrDoz19wz7qK7tYeu62', 'https://open.spotify.com/track/3sd2p4kE7xQmFH3lPnFl6h', 'https://open.spotify.com/track/68Dni7IE4VyPkTOH9mRWHr', 'https://open.spotify.com/track/00Blm7zeNqgYLPtW6zg8cj', 'https://open.spotify.com/track/0u2P5u6lvoDfwTYjAADbn4', 'https://open.spotify.com/track/0RiRZpuVRbi7oqRdSMwhQY', 'https://open.spotify.com/track/37y7iDayfwm3WXn5BiAoRk', 'https://open.spotify.com/track/3GZD6HmiNUhxXYf8Gch723', 'https://open.spotify.com/track/2vmfvSoZBFAt9hhRoEByLi', 'https://open.spotify.com/track/6ws54n2IzyrIxxyzlG2bVJ', 'https://open.spotify.com/track/0fea68AdmYNygeTGI4RC18', 'https://open.spotify.com/track/3o9kpgkIcffx0iSwxhuNI2', 'https://open.spotify.com/track/3Kkjo3cT83cw09VJyrLNwX', 'https://open.spotify.com/track/7qEHsqek33rTcFNT9PFqLf', 'https://open.spotify.com/track/1v7L65Lzy0j0vdpRjJewt1', 'https://open.spotify.com/track/3XjN0mvFkQp1FMVM9Ro5hm', 'https://open.spotify.com/track/2gpWyfu7eZ01zzncHpxOtA', 'https://open.spotify.com/track/2J2Z1SkXYghSajLibnQHOa', 'https://open.spotify.com/track/1jIMjbzcGCcCQn5iMu9CUc', 'https://open.spotify.com/track/1XGmzt0PVuFgQYYnV2It7A', 'https://open.spotify.com/track/2tpWsVSb9UEmDRxAl1zhX1', 'https://open.spotify.com/track/0gucTLf7trAf37Ua1uAyAu', 'https://open.spotify.com/track/74WROFXsox6wkeUrEK2DS6', 'https://open.spotify.com/track/5g7sDjBhZ4I3gcFIpkrLuI', 'https://open.spotify.com/track/503OTo2dSqe7qk76rgsbep', 'https://open.spotify.com/track/40w8JmvwYUP2HUiXPxjy99', 'https://open.spotify.com/track/2tGvwE8GcFKwNdAXMnlbfl', 'https://open.spotify.com/track/3yMC1KsTwh0ceXdIe4QQAQ', 'https://open.spotify.com/track/69vlMrzHwATKzupwNcUPyK', 'https://open.spotify.com/track/1ZdhOMWyFR8Iv9eylMGYg2', 'https://open.spotify.com/track/6Y46tOTRhkBamosyuWa6YX', 'https://open.spotify.com/track/0k4d5YPDr1r7FX77VdqWez', 'https://open.spotify.com/track/0sTlGEld0h8kIPZaKDYUf4', 'https://open.spotify.com/track/0MMyJUC3WNnFS1lit5pTjk', 'https://open.spotify.com/track/4u7EnebtmKWzUH433cf5Qv', 'https://open.spotify.com/track/7qiZfU4dY1lWllzX7mPBI3', 'https://open.spotify.com/track/5TXDeTFVRVY7Cvt0Dw4vWW', 'https://open.spotify.com/track/7hU3IHwjX150XLoTVmjD0q', 'https://open.spotify.com/track/5JCoSi02qi3jJeHdZXMmR8', 'https://open.spotify.com/track/7EkWXAI1wn8Ii883ecd9xr', 'https://open.spotify.com/track/1u8c2t2Cy7UBoG4ArRcF5g', 'https://open.spotify.com/track/2Gq636OOGgxCTqEuzCZhsa', 'https://open.spotify.com/track/6HJIZUOiZDE814XMhRGSZN', 'https://open.spotify.com/track/0ct6r3EGTcMLPtrXHDvVjc', 'https://open.spotify.com/track/6RUKPb4LETWmmr3iAEQktW', 'https://open.spotify.com/track/3jjujdWJ72nww5eGnfs2E7', 'https://open.spotify.com/track/1DIXPcTDzTj8ZMHt3PDt8p', 'https://open.spotify.com/track/7yq4Qj7cqayVTp3FF9CWbm', 'https://open.spotify.com/track/0bBd6K5X4W7t9GyXcaVOA7', 'https://open.spotify.com/track/2BcMwX1MPV6ZHP4tUT9uq6', 'https://open.spotify.com/track/5E30LdtzQTGqRvNd7l6kG5', 'https://open.spotify.com/track/003vvx7Niy0yvhvHt4a68B', 'https://open.spotify.com/track/4xkOaSrkexMciUUogZKVTS', 'https://open.spotify.com/track/78kygHp1dvW1kncYjBgbe1', 'https://open.spotify.com/track/0tgVpDi06FyKpA1z0VMD4v', 'https://open.spotify.com/track/7afaZ37wJJL6880z1NRgJS', 'https://open.spotify.com/track/6f5ExP43esnvdKPddwKXJH', 'https://open.spotify.com/track/3dYD57lRAUcMHufyqn9GcI', 'https://open.spotify.com/track/1ZMiCix7XSAbfAJlEZWMCp', 'https://open.spotify.com/track/3XOalgusokruzA5ZBA2Qcb', 'https://open.spotify.com/track/4QWumyD2uwiePBBha9XBHI', 'https://open.spotify.com/track/0G2zPzWqVjR68iNPmx2TBe', 'https://open.spotify.com/track/1zi7xx7UVEFkmKfv06H8x0', 'https://open.spotify.com/track/0nrRP2bk19rLc0orkWPQk2', 'https://open.spotify.com/track/21jGcNKet2qwijlDFuPiPb', 'https://open.spotify.com/track/4jPy3l0RUwlUI9T5XHBW2m', 'https://open.spotify.com/track/2N8m6CYs74qQO4mjVcXO30', 'https://open.spotify.com/track/4xqrdfXkTW4T0RauPLv3WA', 'https://open.spotify.com/track/5vUnjhBzRJJIAOJPde6zDx', 'https://open.spotify.com/track/7JJmb5XwzOO8jgpou264Ml', 'https://open.spotify.com/track/0bI7K9Becu2dtXK1Q3cZNB', 'https://open.spotify.com/track/22skzmqfdWrjJylampe0kt', 'https://open.spotify.com/track/1Y5Jvi3eLi4Chwqch9GMem', 'https://open.spotify.com/track/2Foc5Q5nqNiosCNqttzHof', 'https://open.spotify.com/track/48QmG1dfvMuYLxMPt7KSRA', 'https://open.spotify.com/track/6v3KW9xbzN5yKLt9YKDYA2', 'https://open.spotify.com/track/7BDHDiidJ8WV349p3HTxTV', 'https://open.spotify.com/track/161DnLWsx1i3u1JT05lzqU', 'https://open.spotify.com/track/6Jrdb6CFOJEGaHjaa6c4WR', 'https://open.spotify.com/track/7KA4W4McWYRpgf0fWsJZWB', 'https://open.spotify.com/track/7iL6o9tox1zgHpKUfh9vuC', 'https://open.spotify.com/track/5lAnYvAIkSDNXqfo7DyFUm', 'https://open.spotify.com/track/4bV5sf2B4hWBBd5HQ8S7KB', 'https://open.spotify.com/track/7BqBn9nzAq8spo5e7cZ0dJ', 'https://open.spotify.com/track/1WCEAGGRD066z2Q89ObXTq', 'https://open.spotify.com/track/3UmaczJpikHgJFyBTAJVoz', 'https://open.spotify.com/track/45S5WTQEGOB1VHr1Q4FuPl', 'https://open.spotify.com/track/2SLwbpExuoBDZBpjfefCtV', 'https://open.spotify.com/track/3Oww84xrmgjyr5J1ilOmAf', 'https://open.spotify.com/track/35mvY5S1H3J2QZyna3TFe0', 'https://open.spotify.com/track/0W6I02J9xcqK8MtSeosEXb', 'https://open.spotify.com/track/5719MEdRQcH4c3phXqX7WN', 'https://open.spotify.com/track/3TSLqZssCoCdDlMhCJ08XW', 'https://open.spotify.com/track/48q0vSHcJdhK3IiXH8C5WJ', 'https://open.spotify.com/track/0UXlu64mDLvfzR8IXMz06J', 'https://open.spotify.com/track/3U4isOIWM3VvDubwSI3y7a', 'https://open.spotify.com/track/4cktbXiXOapiLBMprHFErI', 'https://open.spotify.com/track/5enxwA8aAbwZbf5qCHORXi', 'https://open.spotify.com/track/32BeYxKPrig1LefHsC0Xuo', 'https://open.spotify.com/track/6EtKlIQmGPB9SX8UjDJG5s', 'https://open.spotify.com/track/7FIWs0pqAYbP91WWM0vlTQ', 'https://open.spotify.com/track/2ZRo7axmMPeSVUvDbGkJah', 'https://open.spotify.com/track/0B7wvvmu9EISAwZnOpjhNI', 'https://open.spotify.com/track/3rq5w4bQGigXOfdN30ATJt', 'https://open.spotify.com/track/285pBltuF7vW8TeWk8hdRR', 'https://open.spotify.com/track/2BEcap3xJtmiPaHKyfQi4e', 'https://open.spotify.com/track/2VxeLyX666F8uXCJ0dZF8B']
Now that we have a list containing each song ID, we can gather specific song data from the API. In order to simplify the data collection process, I will be gathering data from the first 10 songs in the Top Charts and my personal listening data. Below, I will show the steps to acquire the 'valence', 'danceability', and 'tempo' of the songs.
#newSongID = [x.replace('https://open.spotify.com/track/','') for x in songIDList]
chartIDList = [] # list to store the top 10 tracks' IDs
for i in range(2,12): # for loop to capture the top 10 tracks, begins at 2 to eliminate 'nan' and 'URL' from the list
chartIDList.append(songIDList[i].replace('https://open.spotify.com/track/',''))# replaces the url with nothing
# then adds the ID to the chart list
chartIDList
['4LRPiXqCikLlN15c3yImP7', '1rDQ4oMwGJI7B4tovsBOxc', '02MWAaffLxlfxAUY7c5dvx', '5PjdY0CKGZdEuoNab3yDmX', '1HhNoOuqm1a5MXYEgAFl8o', '3FkeNbs9Zeiqkr3WkbOiGp', '2DB4DdfCFMw1iaR6JaR03a', '5Z9KJZvQzH6PFmb8SNkxuk', '7rglLriMNBPAyuJOMGwi39', '4fouWK6XVHhzl78KzQ1UjL']
chartValenceList = [] # list to store the valence data
chartTempoList = [] # list to store the tempo data
chartDanceList = [] # list to store the danceability data
for i in range(len(chartIDList)): # for loop running within the length of the chart id list
currentRequest = requests.get("https://api.spotify.com/v1/audio-features/"+str(chartIDList[i]), headers=headers).json()
# requests the current ID in the for loop, headers is required for authentication
#print(currentRequest)
chartValenceList.append(currentRequest['valence']) # accesses the dictionary for valence and adds it to the list
chartTempoList.append(currentRequest['tempo']) # same as above but for tempo
chartDanceList.append(currentRequest['danceability']) # same as above but for danceability
print(chartDanceList)
print(chartTempoList)
print(chartValenceList)
[0.52, 0.905, 0.761, 0.591, 0.728, 0.812, 0.756, 0.741, 0.795, 0.695] [173.93, 106.998, 80.87, 169.928, 77.011, 91.993, 94.996, 150.087, 116.032, 121.932] [0.662, 0.324, 0.531, 0.478, 0.555, 0.396, 0.956, 0.892, 0.934, 0.415]
From the code above, we have accessed the API to produce lists of the danceability, tempo, and valence of the top 10 tracks listened to during the week of 4/21/22. Now, we must access my personal json file containing my listening history. We will collect data from the first ten tracks.
personalHistory = pd.read_json("StreamingHistory3.json")
personalHistory
endTime | artistName | trackName | msPlayed | |
---|---|---|---|---|
0 | 2022-04-21 03:42 | San Holo | heal (↑%) | 221500 |
1 | 2022-04-21 03:46 | Calvin Harris | Outside (feat. Ellie Goulding) | 227266 |
2 | 2022-04-21 03:51 | Daft Punk | Digital Love | 301373 |
3 | 2022-04-21 03:56 | Daft Punk | One More Time | 320357 |
4 | 2022-04-21 04:00 | Lemaitre | Stepping Stone | 256418 |
... | ... | ... | ... | ... |
374 | 2022-04-22 23:28 | Spiritbox | Perennial | 246480 |
375 | 2022-04-22 23:31 | Currents | Let Me Leave | 201011 |
376 | 2022-04-22 23:35 | Currents | Poverty of Self | 205669 |
377 | 2022-04-22 23:39 | Currents | Origin | 244768 |
378 | 2022-04-22 23:43 | Beartooth | I Have a Problem | 240029 |
379 rows × 4 columns
As we can see from the above file preview, the JSON file provided by spotify does not include the specific track ID with each track I have listened to. This means I will have to search each track using the api, and extract the track ID from there.
For the sake of creating more interesting data, I will be using 0-4 tracks and 374-378 (the tracks shown in the preview).
I picked another song, Bleach Bath by Spiritbox, to replace Origin by Currents, as the API search was too long to find the track ID I needed.
I frequently repeat these songs, so the data will not be inaccurate when comparing it to the Top 10 charts data. I am choosing these specific songs to gather a more diverse set of genres (0-4 is electronic, 374-378 is metal).
Due to the missing track ID in the JSON file given by Spotify, I will be making individual requests to search each track by name, finding the corresponding dictionary for said track, finding the ID, then adding specific dance, tempo, and valence stats to lists.
trackNames = ["heal (↑%)","Outside (feat. Ellie Goulding)", "Digital Love", "One More Time" ,"Stepping Stone", "Perennial",
"Let Me Leave", "Poverty of Self", "Bleach Bath", "I Have a Problem"]
# I created a list of the track names in order to streamline the process of making individual requests.
# Request for track one
personalDanceList = []
personalTempoList = []
personalValenceList = []
# Creating the lists to hold the values for Dance, Tempo, and Valence for each song.
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[0]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[1]['id']
# Here, I am requesting the API search with the track name. Then, I create the variables "Variable" and "anotherVariable"
# to access the specific dictionarys I need. From there, I iterate through the list and access the "id" key
# to find the track ID for the specific song.
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[1]['id'], headers=headers).json()
testRequest
# This is the same request used for the Top 10 Charts tracks. I call the desired ID and retrieve the track's specific stats.
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
# I print the lists after each run to make sure the values are being added.
[0.212] [128.28] [0.512]
# Request for track two, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[1]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418] [128.28, 128.035] [0.512, 0.646]
# Request for track three, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[2]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53] [128.28, 128.035, 124.726] [0.512, 0.646, 0.644]
# Request for track four, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[3]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53, 0.476] [128.28, 128.035, 124.726, 122.746] [0.512, 0.646, 0.644, 0.613]
# Request for track five, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[4]+"&type=track", headers=headers).json()
#historyRequest
#6qsjIsKDkpnb8Z1UxozO8O
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[6]['id']
# List has an index of 6 due to the amount of tracks with the name "Stepping Stone"
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[6]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53, 0.476, 0.416] [128.28, 128.035, 124.726, 122.746, 92.03] [0.512, 0.646, 0.644, 0.613, 0.579]
# Request for track six, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[5]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53, 0.476, 0.416, 0.2] [128.28, 128.035, 124.726, 122.746, 92.03, 124.901] [0.512, 0.646, 0.644, 0.613, 0.579, 0.443]
# Request for track seven, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[6]+"&type=track", headers=headers).json()
historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53, 0.476, 0.416, 0.2, 0.224] [128.28, 128.035, 124.726, 122.746, 92.03, 124.901, 120.114] [0.512, 0.646, 0.644, 0.613, 0.579, 0.443, 0.494]
# Request for track eight, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[7]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53, 0.476, 0.416, 0.2, 0.224, 0.15] [128.28, 128.035, 124.726, 122.746, 92.03, 124.901, 120.114, 115.087] [0.512, 0.646, 0.644, 0.613, 0.579, 0.443, 0.494, 0.494]
# Request for track nine, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[8]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53, 0.476, 0.416, 0.2, 0.224, 0.15, 0.343] [128.28, 128.035, 124.726, 122.746, 92.03, 124.901, 120.114, 115.087, 130.079] [0.512, 0.646, 0.644, 0.613, 0.579, 0.443, 0.494, 0.494, 0.257]
# Request for track ten, same exact code as above
historyRequest = requests.get("https://api.spotify.com/v1/search?q="+trackNames[9]+"&type=track", headers=headers).json()
#historyRequest
variable=historyRequest['tracks']
anotherVariable = variable['items']
anotherVariable[0]['id']
testRequest = requests.get("https://api.spotify.com/v1/audio-features/"+anotherVariable[0]['id'], headers=headers).json()
#testRequest
personalValenceList.append(testRequest['valence']) # accesses the dictionary for valence and adds it to the list
personalTempoList.append(testRequest['tempo']) # same as above but for tempo
personalDanceList.append(testRequest['danceability']) # same as above but for danceability
print(personalValenceList)
print(personalTempoList)
print(personalDanceList)
[0.212, 0.418, 0.53, 0.476, 0.416, 0.2, 0.224, 0.15, 0.343, 0.241] [128.28, 128.035, 124.726, 122.746, 92.03, 124.901, 120.114, 115.087, 130.079, 104.991] [0.512, 0.646, 0.644, 0.613, 0.579, 0.443, 0.494, 0.494, 0.257, 0.534]
Finally, all the desired data from the Spotify API has been gathered! Below are printouts of the Top 10 Songs and my personal Top 10 tracks during the period of ().
print("Top 10 Charts VS Personal Valence Values")
print(chartValenceList)
print(personalValenceList)
print()
print("Top 10 Charts VS Personal Dance Values")
print(chartDanceList)
print(personalDanceList)
print()
print("Top 10 Charts VS Personal Tempo Values")
print(chartTempoList)
print(personalTempoList)
Top 10 Charts VS Personal Valence Values [0.662, 0.324, 0.531, 0.478, 0.555, 0.396, 0.956, 0.892, 0.934, 0.415] [0.212, 0.418, 0.53, 0.476, 0.416, 0.2, 0.224, 0.15, 0.343, 0.241] Top 10 Charts VS Personal Dance Values [0.52, 0.905, 0.761, 0.591, 0.728, 0.812, 0.756, 0.741, 0.795, 0.695] [0.512, 0.646, 0.644, 0.613, 0.579, 0.443, 0.494, 0.494, 0.257, 0.534] Top 10 Charts VS Personal Tempo Values [173.93, 106.998, 80.87, 169.928, 77.011, 91.993, 94.996, 150.087, 116.032, 121.932] [128.28, 128.035, 124.726, 122.746, 92.03, 124.901, 120.114, 115.087, 130.079, 104.991]
Now let's use this data to answer some questions.
import seaborn as sb # importing seaborn for plotting
# making a pandas dataframe to organize the data
columns = ['Top 10 Tempo','Personal 10 Tempo','Top 10 Dance','Personal 10 Dance','Top 10 Valence','Personal 10 Valence']
# list of names for the columns
index = ["Track 1","Track 2","Track 3","Track 4","Track 5","Track 6","Track 7","Track 8","Track 9","Track 10",]
# list of names for the rows
musicDataFrame = pd.DataFrame(list(zip(chartTempoList,personalTempoList,chartDanceList,personalDanceList,
chartValenceList,personalValenceList)),index,columns)
musicDataFrame
Top 10 Tempo | Personal 10 Tempo | Top 10 Dance | Personal 10 Dance | Top 10 Valence | Personal 10 Valence | |
---|---|---|---|---|---|---|
Track 1 | 173.930 | 128.280 | 0.520 | 0.512 | 0.662 | 0.212 |
Track 2 | 106.998 | 128.035 | 0.905 | 0.646 | 0.324 | 0.418 |
Track 3 | 80.870 | 124.726 | 0.761 | 0.644 | 0.531 | 0.530 |
Track 4 | 169.928 | 122.746 | 0.591 | 0.613 | 0.478 | 0.476 |
Track 5 | 77.011 | 92.030 | 0.728 | 0.579 | 0.555 | 0.416 |
Track 6 | 91.993 | 124.901 | 0.812 | 0.443 | 0.396 | 0.200 |
Track 7 | 94.996 | 120.114 | 0.756 | 0.494 | 0.956 | 0.224 |
Track 8 | 150.087 | 115.087 | 0.741 | 0.494 | 0.892 | 0.150 |
Track 9 | 116.032 | 130.079 | 0.795 | 0.257 | 0.934 | 0.343 |
Track 10 | 121.932 | 104.991 | 0.695 | 0.534 | 0.415 | 0.241 |
# visualisation for question 1
# “How does the Spotify emotional data of my personal listening history compare to the top 10 songs during the week of 4/21/22?”
musicMelt = musicDataFrame.melt(var_name="Data Category")
a = pd.DataFrame(musicMelt.iloc[40:60])
a
Data Category | value | |
---|---|---|
40 | Top 10 Valence | 0.662 |
41 | Top 10 Valence | 0.324 |
42 | Top 10 Valence | 0.531 |
43 | Top 10 Valence | 0.478 |
44 | Top 10 Valence | 0.555 |
45 | Top 10 Valence | 0.396 |
46 | Top 10 Valence | 0.956 |
47 | Top 10 Valence | 0.892 |
48 | Top 10 Valence | 0.934 |
49 | Top 10 Valence | 0.415 |
50 | Personal 10 Valence | 0.212 |
51 | Personal 10 Valence | 0.418 |
52 | Personal 10 Valence | 0.530 |
53 | Personal 10 Valence | 0.476 |
54 | Personal 10 Valence | 0.416 |
55 | Personal 10 Valence | 0.200 |
56 | Personal 10 Valence | 0.224 |
57 | Personal 10 Valence | 0.150 |
58 | Personal 10 Valence | 0.343 |
59 | Personal 10 Valence | 0.241 |
sb.catplot(x="Data Category", y="value",data=a,kind="bar")
<seaborn.axisgrid.FacetGrid at 0x22b5f242f10>
The above graph compares the average valence between the Top 10 tracks of the week of 4/21/22, and my personal top 10 tracks listened to during the same period. As we can see, there is a significant negative different between my personal tracks and the top 10. The vertical bars inside each bar are "error bars", which represent one standard deviation of uncertainty. Even with this measurement accounted for in the graph, there is a significant difference between the valence values of my personal music and the top 10 tracks.
# visualisation for question 2
# “Does an increase in tempo mean an increase in valence?”
sb.lineplot(x="Personal 10 Tempo",y="Personal 10 Valence",data=musicDataFrame)
<AxesSubplot:xlabel='Personal 10 Tempo', ylabel='Personal 10 Valence'>
This line plot graphs the valence and tempo from my personal top 10 tracks. The graph begins with a steady negative trend. As valence goes down, tempo increases. Then, there are sharp increases in valence within the higher tempos presented in the data. From this data, we can confirm that an increase in tempo does not cause a definite increase in valence. The unsteady direction of this graph could be explained by the different genres of the tracks. With the top 10 tracks from the listening charts, all songs used for data gathering are Pop, whereas I chose some electronic music and some metal music.
# visualisation for question 3
# “Does an increase in tempo mean an increase in danceability?”
sb.lineplot(x="Top 10 Tempo",y="Top 10 Dance",data=musicDataFrame)
<AxesSubplot:xlabel='Top 10 Tempo', ylabel='Top 10 Dance'>
This line plot graphs the danceability and tempo from the top 10 tracks from the listening charts. The graph shows no definite trend between tempo and danceability. This could be explained by the other measurement Spotify gathers for each song, such as energy, liveness, and speechiness.