Music

Whats the deal

I wanted to visualize the predominant genres showcased at the Electric Daisy Carnival (EDC), offering valuable insights into trends within the electronic music industry. In doing so, I seek to gain a deeper understanding of market demands and cultural shifts.

Plan

I wanted to build out a project to test my analyst knowledge and build something to combine SQL, Python, Tableau, and Analysis. My aim was to uncover trends within a niche and personally intriguing market. I also wanted to play with the Spotify API and thus decided to analyze trends within the Electronic Music industry.

I wanted to limit my dataset so I decided to focus on artists who have performed at the Electric Daisy Carnival in Las Vegas, believing this selection would encompass both established and emerging talents in the electronic music scene with the barrier to entry that they are somewhat commercially popular. In doing so, I want to acknowledge that my analysis is constrained by various factors that, for a detailed understanding of these limitations and potential solutions, I will provide documentation on analysis limitations below.

I broke down the project into phases, with each phase building functionality on the previous one. Initially, I will develop a rudimentary (I studied accounting, not CS!) Python script to call the Spotify API and retrieve genres and other information for a list of artists. I will then compile a list of artists who have performed at EDC and scrape their year of performance and set time. (The significance of set time lies in its potential correlation with popular genres, but I’ve kept this out of scope for now.) While not entirely necessary due to the small dataset, I aim to populate this data into a database to gain practice. Following this, I will execute SQL queries to pull the final dataset into Tableau Public (Im cheap). The focus of the project is to generate a Tableau dashboard with metrics, with the main metric being the top genres by stage. Visually, I envision the dashboard as an interactive map of the festival, allowing users to filter the data by stage.

Step 1 – The backbone

import pandas as pd
from dotenv import load_dotenv
import os
import base64
from requests import post, get
import json

load_dotenv()

client_id = os.getenv("CLIENT_ID")
client_secret = os.getenv("CLIENT_SECRET")

def get_token():
    auth_string = client_id + ":" + client_secret
    auth_bytes = auth_string.encode("utf-8")
    auth_base64 = str(base64.b64encode(auth_bytes), "utf-8")

    url = "https://accounts.spotify.com/api/token"
    headers = {
        "Authorization": "Basic " + auth_base64,
        "Content-Type": "application/x-www-form-urlencoded"
    }
    data = {"grant_type": "client_credentials"}
    result = post(url, headers=headers, data=data)
    json_result = json.loads(result.content)
    token = json_result["access_token"]
    return token

def get_auth_header(token):
    return {"Authorization": "Bearer " + token}

def search_for_artist(token, artist_name):
    url = "https://api.spotify.com/v1/search"
    headers = get_auth_header(token)
    query = f"?q={artist_name}&type=artist&limit=1"
    query_url = url + query
    result = get(query_url,headers=headers)
    json_result = json.loads(result.content)["artists"]["items"]
    if len(json_result) == 0:
        print(f"No artist found for {artist_name}")
        return None
    return json_result[0]

def get_genres_by_artists(token, artist_id):
    url = f"https://api.spotify.com/v1/artists/{artist_id}"
    headers = get_auth_header(token)
    result = get(url, headers=headers)
    json_result = json.loads(result.content)["genres"]
    return json_result

def get_genres_for_artists_from_excel(input_file, output_file):
    token = get_token()
    data = pd.read_excel(input_file, usecols=['Artist'])
    genres_list = []

    for artist_name in data['Artist']:
        artist_result = search_for_artist(token, artist_name)
        if artist_result:
            genres = get_genres_by_artists(token, artist_result["id"])
            genres_list.append(", ".join(genres))
        else:
            genres_list.append("Not Found")

    data['Genres'] = genres_list
    data.to_excel(output_file, index=False)

if __name__ == "__main__":
    input_file = "/Users/devicente/Desktop/Projects/SpotifyAPI/EDC Artists.xlsx"
    output_file = "/Users/devicente/Desktop/Projects/SpotifyAPI/output.xlsx"
    get_genres_for_artists_from_excel(input_file, output_file)
    print("It worked!")

I wrote the following Python script to take a workbook of artists, access the Spotify API and return information about the artists. This current version only returns the artist’s genre as defined by Spotify. This is the first issue I can see in terms of limitation of analysis. Genres are subjective. It can be argued that in using Spotify’s API, it would perform a baseline determination of genres such that it is not left to the subjectivity of a single person.

Step 2: Database

Data regarding artist rosters is readily available in nice Excel sheets provided by the great people of reddit. So I modified an SEO bot to scrape threads using chat-GPT. No need to over complicate the easy parts. I pulled the rosters from threads and spot checked the rosters (we may be losing a few last minute artist changes, but more on that later). We do want to over-complicate the fun stuff so over lunch I quickly sketched out a Entity Relationship Diagram for my data:

And here it is beautified:

Some considerations on this ERD draft. While I have experience in SQL, I don’t typically build databases from scratch. A few things I will look into that may already identify themselves as I am bringing this into postgreSQL.
-Probably need a relationship between EDC and stage
-Probably need to reconfigure date and year for EDC
-Probably could share some kind of composite key for Set

Need to combine data to have a better visual. Feel like – while this will work, we are losing clarity/flexibility/efficency.

Step 3: API Results

As anticipated, pushing my artist list through the Spotify API has returned some… interesting results. In my research I found the following from the man himself, Glenn McDonald, Spotify’s former data alchemist (I’m a huge fan Glenn, can’t wait for the book to drop!):

The genre tags you see in the API are for artists who we (Spotify) consider representative for those genres. Internally we have a larger mapping of less-representative artists to their probably-relevant genres…. Genre assignments are a combination of human curation and algorithmic extrapolation, so in most genres it’s quite possible for artists to qualify as representative (and thus appear in Sound or Intro playlists) based on listening patterns.

Glenn McDonald, 2022

Limiting the data to the 2024 EDC artist list, of the 236 Artists, 43 are not assigned a genre. The missing genre information for 43 out of 236 artists presents a significant challenge for accurate data analysis and interpretation. While utilizing the API was intended to reduce biases, the gaps in data re-introduces unanticipated biases and limitations. Implementing an effective mitigation strategy and acknowledging these gaps may help in managing the impact and improve the the derived results… if the data was perfect beyond these holes.

Additionally, in completing spot checks there are uh… issues. The “backbone” will only return one artist, which is defaulted to the most popular artist. The issue is that DJ’s love to pick very commonplace names. In a run-through of the data, artists like IVY and Richter are returning popular artists with similar names and VASTLY different Genres.

Because the API did not return a genre for 42 out of a list of 220 artists, a significant data gap that can skew understanding of genre trends and popularity. This missing data limits ability to perform a comprehensive and accurate analysis, as it omits a considerable portion of the artist pool, potentially excluding emerging or niche genres that would be critical to understanding current music trends. Additionally, the current “backbone” approach of returning only the most popular artists may lead to a skewed perspective. Popularity does not necessarily equate to representativeness, as it can disproportionately highlight mainstream artists while neglecting those who may be influential within specific sub-genres or emerging scenes (Go Listen to Richter). I approached this project with the hope to have data-driven insights, so it is crucial for me to have a holistic view of artist and accurately captured genre information. Hopefully to ensure that insights are not biased by popularity metrics and reflect the true dynamics of the analysis I set out to achieve. I am going to resolve the following before continuing (should be around October when busy season ends for me – Where I plan on implementing a few mitigation ideas (searching by related artists or searching genres of several artists and returning by established “category”). Until then, please feel free to review the list below:

ArtistArtist Genre
AbanaNo genres found
Acrazepop dance, tech house
Adam Beyerdark techno, minimal techno, raw techno, schranz, swedish electronic, swedish techno, techno
Adam Xdark techno
Adrenalizeclassic hardstyle, euphoric hardstyle, rawstyle
Adventure Clubbrostep, canadian electronic, complextro, edm, electro house, filthstep, pop dance
Airwolf Paradiseaustralian house
AlchimystNo genres found
Alessodance pop, edm, pop, pop dance, progressive electro house
Alison Wonderlandaussietronica, edm, electra, electronic trap, escape room, indietronica
Aly & Filadance pop, girl group, post-teen pop
Andrew Bayerprogressive house, progressive trance, trance, uplifting trance
Andrew Rayeledm, moldovan pop, pop dance, progressive house, trance
Andrussmexican tech house, tech house
Angerfisthardcore techno, tekk, uptempo hardcore
ArgyNo genres found
Armin Van Buurendutch trance, edm, pop dance, progressive house, trance
Atliensbrostep, dubstep
Atmozfearsclassic hardstyle, euphoric hardstyle, rawstyle
Audiofreqclassic hardstyle, euphoric hardstyle, rawstyle
Azzeccatech house
Beclatin pop, latin viral pop, rap latina, reggaeton, trap latino, urbano latino
Ben Hemsleyuk house
Ben Sterlingtech house, uk tech house
Benny Benassidutch house, edm, electro house, pop dance
Blastoyzpsychedelic trance
Boogie Tbrostep
Bouconnecticut hardcore, metallic hardcore
Brina KnaussNo genres found
Bryan Kearneytrance, uplifting trance
Calussaafro house
Camden Coxstutter house
Carl Coxhouse, schranz, uk tech house
Caspabrostep, classic dubstep, filthstep, glitch hop
Cassianmelodic house
Chef Boyarbeatzdowntempo bass
Chelina Manuhutudutch tech house
ClawzNo genres found
Crankdatdubstep
Creeds + Helen Kahypertechno
Cristophhouse, melodic house, progressive house
D-Sturbclassic hardstyle, euphoric hardstyle, frenchcore, rawstyle, xtra raw
D. ZeledonNo genres found
Da Tweekazclassic hardstyle, euphoric hardstyle
Dabincanadian electronic, melodic dubstep, pop edm
DarksiderzNo genres found
David Guettabig room, dance pop, edm, pop, pop dance
Daxsonprogressive trance
Dead Xgym hardstyle
Deadly Gunsfrenchcore, uptempo hardcore
Deadmau5canadian electronic, complextro, edm, electro house, pop dance, progressive house
Death CodeNo genres found
Deborah De Lucaelectra, italian techno
Deeper Purposebass house, tech house, uk tech house
Deorrodutch house, edm, electro house, melbourne bounce, melbourne bounce international, pop dance, progressive electro house
Devaultvapor twitch
Devin Wildclassic hardstyle, euphoric hardstyle, rawstyle
Dillon Francisbrostep, edm, electro house, moombahton, pop dance, progressive electro house, slap house
Dimensiondancefloor dnb, drum and bass, uk dnb
Diplodance pop, edm, electro house, moombahton, pop dance
DJ Minxdetroit house
DJ Snakeedm, electronic trap, pop, pop dance
Dom Dollaaustralian house, deep groove house, house
DominaNo genres found
Eli Brownhouse, tech house, uk dance
EmorfikNo genres found
Eric Prydzedm, electro house, house, pop dance, progressive electro house, progressive house
Excisionbrostep, canadian electronic, filthstep
FallenNo genres found
Ferry Corstendutch trance, progressive house, progressive trance, trance, uplifting trance
Fisheraustralian house, house
Four Tetelectronica, folktronica, indietronica, intelligent dance music, trip hop
Fred Againedm, house, stutter house
FrosttopNo genres found
Geocontemporary country, country, country road
Ghastly Presents GhengarNo genres found
Giuseppe Ottavianiitalian trance, progressive house, trance, uplifting trance
GravedgrNo genres found
Green Velvetdeep disco house, house, minimal techno, tech house
Gryffinedm, pop dance
HabstractNo genres found
Hamdibassline
Hannah LaingNo genres found
Hedexbelgian dnb
Heidi LawdenNo genres found
Hi-Lodutch house, electro house, house
HivemindNo genres found
Hixxydeep happy hardcore, happy hardcore, hardcore techno
Hol!dubstep, gaming dubstep
Honeyluvtech house
Hugeldeep house
Illeniumedm, melodic dubstep, pop dance
Indira PaganottoNo genres found
Infected Mushroompsychedelic trance
Ivylatin hip hop, rap latina, reggaeton, trap latino, urbano latino
J. Worrabass house, house, tech house
Jamie Jonesdeep disco house, deep house, house, minimal techno, uk tech house
Jeaniedubstep, speed house
Jerome Isma-Aemunich electronic, progressive house
Jessica Audiffreddubstep, mexican edm
John 00 FlemingNo genres found
John Summithouse, pop dance, uk dance
JolucaNo genres found
Jon Caseysouth african electronic
Joseph Capriatiitalian techno, minimal techno, techno
Joyrydebass house, brostep, edm, electro house, electronic trap
Kai Wachibrostep, deathstep, dubstep
Kasablancamelodic house
Kaskadeedm, electro house, pop dance, progressive electro house, progressive house, vocal house
Kayzobrostep, speed house
KeltekNo genres found
Kevin De Vriesdark techno
Kevin Saundersonacid house, detroit techno, minimal techno, techno
Khivaexperimental bass
KhomhaNo genres found
Klangkuenstlerdark techno, deep euro house, hard techno, raw techno
Kovenchillstep, melodic dubstep
Kreampop dance
KreationNo genres found
Kyle Walkerbass house, tech house
Lady Faithhardstyle
Layzdubstep
Level UpNo genres found
LevenkhanNo genres found
Lf Systemuk dance
Lil TexasNo genres found
Lilly Palmerswiss techno
Loco Dicegerman techno, minimal techno, techno
Lost Frequenciesbelgian edm, edm, pop dance, tropical house
LsdreamNo genres found
Luttrellmelodic house, progressive house
Maddixbig room
Majesticchristian power metal, melodic metal, power metal, swedish power metal, symphonic metal
MalóneNo genres found
Mandydance pop, hollywood, neo mellow, post-teen pop
Maraudabrostep, deathstep, dubstep, tearout
Marcel Dettmannmicrohouse, minimal techno, techno
Markus Schulzedm, pop dance, progressive house, progressive trance, trance
Marshbrostep, edm, pop, progressive electro house
Martin Garrixdutch edm, edm, pop, pop dance, progressive house
Mary DroppinzNo genres found
Matrodabass house, electro house, tech house
Matt Sassarifrench tech house, french techno, tech house
Mau Ptech house
Max Stylerbrostep, tech house
Meléuk house
Mersivexperimental bass
Metta & Glydeneo-classical
Mind Againstdeep techno, italian techno, melodic techno, minimal techno
Miss Dretech house
Mitischillstep, complextro, filthstep, melodic dubstep, pop edm
MiyukiNo genres found
Mkexperimental r&b
Nazalbum rock, classic rock, glam metal, hard rock, rock
Nghtmrebrostep, edm, electro house
Nicole Moudaberarab electronic, deep minimal techno, electra, minimal techno, techno
Nifraprogressive trance
NightstalkerNo genres found
Ninajirachiaussietronica
Noizubass house, house, tech house
Odd Mob X Omnom: Hyperbeamaussietronica, bass house, tech house
Odd Mobaussietronica, bass house, tech house
Omar Santanagabber
Orjan Nilsen & Mark Sixmaprogressive electro house, progressive house, trance, uplifting trance
Ownbossbrazilian edm
Paul Oakenfoldtrance
Paul Van Dykgerman techno, trance, uplifting trance
Peggy Gouelectra, float house
Pocketneo grime
Prydaprogressive electro house, progressive house
Purple Disco Machinedeep house, house
Rated Rdubstep, gaming dubstep
Raybenurbano mexicano
RemkNo genres found
Richterclassical, classical performance, classical piano, russian classical piano
Riordantech house
San Pachotech house
Sara Landrydark techno
Seven Lionsbrostep, complextro, dubstep, edm, electro house, melodic dubstep, pop dance, progressive trance
Shiba Sanbass house, fidget house, french tech house, house, tech house
Shlømofrench techno, minimal dub
SicariaNo genres found
Slanderdubstep
Sofi Tukkeredm
SorenNo genres found
Sosachicago bop, chicago drill, chicago rap, drill, hip hop, rap, trap
Sound Rushclassic hardstyle, euphoric hardstyle, rawstyle
Steve Aokiedm, electro house, pop dance
Sub Focusdancefloor dnb, drum and bass, uk dance
Sub Zero Projecteuphoric hardstyle, rawstyle
Subtronicsbrostep
Svdden Deathdeathstep, dubstep, riddim dubstep
Talla 2Xlcbubble trance, frankfurt electronic, german techno, trance
Tape BNo genres found
Taylor TorrenceNo genres found
Tiëstobig room, brostep, dutch edm, edm, house, pop dance, progressive electro house, slap house, trance
Timmy Trumpetaustralian dance, big room, melbourne bounce, melbourne bounce international
TobehonestNo genres found
Troyboibass trap, electronic trap
Trymfrench techno
Valentino Khanbrostep, edm, electro house, electronic trap, moombahton
Vintage Culturebrazilian edm
Virtual Riotbrostep, complextro, dubstep, filthstep, gaming dubstep
VULLLGURriddim dubstep
Wadeclassic texas country, outlaw country, red dirt, texas country
Warfacerawstyle, xtra raw
Wasted Penguinzclassic hardstyle, euphoric hardstyle
Water Spiritspeed house
Wilkinsondancefloor dnb, drum and bass, uk dance
Will Clarkebass house, house, tech house
Woolibrostep, dubstep
Worshiproots worship, worship
WukiNo genres found
Yosufgym hardstyle
Yottofinnish edm, melodic house, progressive house
Zeddcomplextro, edm, german techno, pop, pop dance
ZingaraNo genres found
ZofNo genres found
Zomboybrostep, edm, glitch
ZuezeuNo genres found

Step 4: Pressing forward (for Database Practice)

Despite the data issues above, I want to get the database practice in. I used PostgresSQL to build my database. Review my PostgresSQL ERD (wonky lines included!) and my SQL to populate the data. I want to provide a write up on the lessons learned in this practice, such as how we change methodology from the sketch above and how i’m not sure if we are implementing best practices as it relates to constraints. As mentioned in the previous chapter, project will be on hold until October while I file my 3rd busy season client (always the auditors-maid, never the Analyst).

CREATE TABLE Artists (
    ArtistID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    ArtistName VARCHAR(100) NOT NULL
);

-- Create Genres Table
CREATE TABLE Genres (
    GenreID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    GenreName VARCHAR(100) NOT NULL
);

CREATE TABLE ArtistGenres (
    ArtistID INT,
    GenreID INT,
    PRIMARY KEY (ArtistID, GenreID),
    FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID),
    FOREIGN KEY (GenreID) REFERENCES Genres(GenreID)
);

CREATE TABLE Stages (
    StageID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    StageName VARCHAR(50) NOT NULL
);

CREATE TABLE Sets (
    SetID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    ArtistID INT,
    StageID INT,
    SetTime TIME,
    Date DATE,
    FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID),
    FOREIGN KEY (StageID) REFERENCES Stages(StageID)
);

INSERT INTO Stages (StageName) VALUES
('Stereobloom'),
('Kinetic Field'),
('Neon Garden'),
('Wasteland'),
('Basspod'),
('Circuit Grounds');

INSERT INTO Artists (ArtistName) VALUES
('Abana'), ('Acraze').....

INSERT INTO Genres (GenreName) VALUES
('acid house'), 
('afro house'), 
('album rock'), 
('arab electronic').......

INSERT INTO Sets (ArtistID, StageID, SetTime, Date) VALUES
((SELECT ArtistID FROM Artists WHERE ArtistName = 'Abana'), (SELECT StageID FROM Stages WHERE StageName = 'Stereobloom'), '04:45', '2024-05-19'),
((SELECT ArtistID FROM Artists WHERE ArtistName = 'Acraze'), (SELECT StageID FROM Stages WHERE StageName = 'Kinetic Field'), '04:13', '2024-05-18').......