R & Spotify – Part 2: Was hörst Du denn gerade so?

Musikgeschmack - statistisch belegt

Vor über einem Jahr habe ich entdeckt, wie man dank des großartigen Pakets spotifyr von Charles Thompson mit R auf so ziemlich alle Audio-Features der Spotify-Datenbank zugreifen kann - also z.B. auf das Tempo und die Grundtonart oder auf Features wie der “Tanzbarkeit” oder der “Energie” bestimmter Songs. Wie das funktioniert habe ich hier beschrieben. Spannend ist es aber natürlich auch, mal einen Blick auf die eigenen Hörgewohnheiten zu werfen - also was, wann und wie oft gehört wurde. Und auch das geht dank spotifyr ziemlich easy…

Wer spotifyr noch nicht installiert hat muss den kleinen Umweg über devtools gehen, da das Paket nicht über CRAN erhältlich ist sondern auf GitHub gehostet wird. Daneben werden noch die Pakete tidyverse, knitr und kableExtra geladen (dazu später etwas mehr):

# devtools::install_github('charlie86/spotifyr')
library(spotifyr)
library(tidyverse)
## Loading tidyverse: ggplot2
## Loading tidyverse: tibble
## Loading tidyverse: tidyr
## Loading tidyverse: readr
## Loading tidyverse: purrr
## Loading tidyverse: dplyr
## Conflicts with tidy packages ----------------------------------------------
## filter(): dplyr, stats
## lag():    dplyr, stats
library(knitr)
library(kableExtra)

Jetzt werden noch die Spotify-ID-Daten (SPOTIFY_CLIENT_ID und SPOTIFY_CLIENT_SECRET ID) benötigt, die man nach der Anmeldung eines Developer-Accounts erhält. (Es kann durchaus sein, dass sich an dieser Stelle einmal der Browser öffnet und euch dazu auffordert, euch bei Spotify einzuloggen).

Sys.setenv(SPOTIFY_CLIENT_ID = "HIER DIE ID EINGEBEN")
Sys.setenv(SPOTIFY_CLIENT_SECRET = "HIER DIE SECRET ID EINGEBEN")
access_token <- get_spotify_access_token(client_id = Sys.getenv('SPOTIFY_CLIENT_ID'), client_secret = Sys.getenv('SPOTIFY_CLIENT_SECRET'))

“Wie hieß der Song von gestern nochmal?”

Um sich nun beispielsweise die Songs anzeigen zu lassen, die man zuletzt via Spotify gehört hat, ist nicht viel mehr nötig, als die Funktion get_my_recently_played():

get_my_recently_played()
## # A tibble: 50 x 18
##    track_name artist_name album_name played_at_utc       context_type
##    <chr>      <chr>       <chr>      <dttm>              <chr>       
##  1 Devonian:… The Ocean   Phanerozo… 2019-03-05 21:48:05 playlist_v2 
##  2 Arrete     Leech       For Bette… 2019-03-05 21:36:59 playlist_v2 
##  3 Linger     The Inters… The Grand… 2019-03-05 21:29:37 album       
##  4 New Maxim  The Inters… The Grand… 2019-03-05 21:28:02 album       
##  5 The Grand… The Inters… The Grand… 2019-03-05 21:24:28 album       
##  6 Smoke Scr… The Inters… The Grand… 2019-03-05 21:20:51 album       
##  7 Antitype   The Inters… The Grand… 2019-03-05 21:16:49 album       
##  8 Man on th… The Inters… The Grand… 2019-03-05 21:10:55 album       
##  9 Mind over… The Inters… The Grand… 2019-03-05 21:06:38 album       
## 10 Don't Thi… The Inters… The Grand… 2019-03-05 21:01:51 album       
## # … with 40 more rows, and 13 more variables: context_uri <chr>,
## #   context_spotify_url <chr>, album_type <chr>, track_number <int>,
## #   track_popularity <int>, explicit <lgl>, album_release_date <chr>,
## #   album_img <chr>, track_uri <chr>, artist_uri <chr>, album_uri <chr>,
## #   track_preview_url <chr>, track_spotify_url <chr>

Und schon erhält man eine Liste der letzten Songs, die über Spotify abgespielt wurden (wie in der Ausgabe ersichtlich, werden allerdings einige Zeilen und Spalten abgeschnitten). Die Funktion lässt sich durch ein paar Zusatzargumente noch anpassen (mehr Details zu den jeweiligen Parametern finden sich bei Spotify). In diesem Fall will ich neben der Namen der Songs nur die Namen der dazugehörigen Künstler und das Abspiel-Datum nebst Uhrzeit sehen. Mit der Spezifikation limit = 10 grenze ich die Liste zudem auf die letzten zehn Songs ein:

get_my_recently_played(limit = 10) %>% 
  select(track_name, artist_name, played_at_utc) 
## # A tibble: 10 x 3
##    track_name         artist_name     played_at_utc      
##    <chr>              <chr>           <dttm>             
##  1 Devonian: Nascent  The Ocean       2019-03-05 21:48:05
##  2 Arrete             Leech           2019-03-05 21:36:59
##  3 Linger             The Intersphere 2019-03-05 21:29:37
##  4 New Maxim          The Intersphere 2019-03-05 21:28:02
##  5 The Grand Delusion The Intersphere 2019-03-05 21:24:28
##  6 Smoke Screen       The Intersphere 2019-03-05 21:20:51
##  7 Antitype           The Intersphere 2019-03-05 21:16:49
##  8 Man on the Moon    The Intersphere 2019-03-05 21:10:55
##  9 Mind over Matter   The Intersphere 2019-03-05 21:06:38
## 10 Don't Think Twice  The Intersphere 2019-03-05 21:01:51

Um mehr Songs zu sehen, lässt sich die Anzahl über die Spezifikationen etwas vergrößern, bei 50 Songs ist allerdings Schluss. Um die resultierende Tabelle etwas übersichtlicher zu gestalten (die Tabellen oben sehen - wie immer bei den Standardausgaben von R - eher mäßig aus), nutze ich die kable()-Funktion des knitr-Pakets mit der sich u.a. HTML-Tabellen erstellen lassen. Zusätzlich verwende ich Funktionen aus dem Paket kableExtra, mit deren Hilfe sich die Tabellen zusätzlich anpassen lassen. In diesem Fall möchte ich eine scrollbare HTML-Tabelle mit einer fest definierten Größe. Eine gute Einführung in die Erstellung von HTML-Tabellen mit kable und kableExtra findet sich übrigens hier.

get_my_recently_played(limit = 50) %>% 
  select(track_name, artist_name, played_at_utc) %>%
  kable() %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
track_name artist_name played_at_utc
Devonian: Nascent The Ocean 2019-03-05 21:48:05
Arrete Leech 2019-03-05 21:36:59
Linger The Intersphere 2019-03-05 21:29:37
New Maxim The Intersphere 2019-03-05 21:28:02
The Grand Delusion The Intersphere 2019-03-05 21:24:28
Smoke Screen The Intersphere 2019-03-05 21:20:51
Antitype The Intersphere 2019-03-05 21:16:49
Man on the Moon The Intersphere 2019-03-05 21:10:55
Mind over Matter The Intersphere 2019-03-05 21:06:38
Don’t Think Twice The Intersphere 2019-03-05 21:01:51
Smile When the Raindrops Fall Imperial Dance Orchestra 2019-03-05 20:57:50
Moon Ray Ella Fitzgerald and Her Famous Orchestra 2019-03-05 14:42:09
Crosby, Columbo and Vallee Dick Robertson 2019-03-05 14:39:09
Copenhagen Earl Hines 2019-03-05 14:36:06
As Long as We Are in Love Fred Rich & His Orchestra 2019-03-05 14:33:35
Jumping At The Woodside Count Basie 2019-03-05 14:30:14
Jig Walk Sam Lanin and The Ipana Troubadours 2019-03-05 14:27:03
What a Difference a Day Made Freddy Martin & His Orchestra 2019-03-05 14:24:23
You Were Meant For Me The Capitolians 2019-03-05 14:21:18
Happy Days Are Here Again Casa Loma Orchestra, Conducted by Glen Gray 2019-03-05 14:18:35
Let’s Misbehave Irving Aaronson and His Commanders 2019-03-05 14:15:15
Katzen Brauchen Furchtbar Viel Musik Cast - Aristocats 2019-03-05 14:12:20
Execution Thirst ASG 2019-03-05 12:52:01
Survive Sunrise ASG 2019-03-05 11:55:12
The Heaven Moon ASG 2019-03-04 23:57:31
Hawks on the Run ASG 2019-03-04 23:57:00
Florida Sleep On ASG 2019-03-04 23:23:01
Lamb Song ASG 2019-03-04 23:19:35
Weekend Money ASG 2019-03-04 23:14:40
Heavy Scars ASG 2019-03-04 23:10:33
God Knows We ASG 2019-03-04 23:06:21
Kubrick Colors ASG 2019-03-04 23:02:19
The Heaven Moon ASG 2019-03-04 22:59:59
Hawks on the Run ASG 2019-03-04 22:56:10
Lightning Song ASG 2019-03-04 22:51:45
Up from My Dreams ASG 2019-03-04 22:47:02
Execution Thirst ASG 2019-03-04 22:42:54
Survive Sunrise ASG 2019-03-04 22:39:58
Survive Sunrise ASG 2019-03-04 22:36:17
Palo Alto Kettcar 2019-03-04 22:32:01
La Forza del Destino: Act II: Scene 1: Canzone - Al suon del tamburo Giuseppe Verdi 2019-03-04 21:38:40
La Forza del Destino: Act II: Scene 1: Scena - La cena è pronta Giuseppe Verdi 2019-03-04 21:26:55
La Forza del Destino: Act II: Scene 1: Coro, Ballabile - Holà, holà, holà! Giuseppe Verdi 2019-03-04 21:24:43
La Forza del Destino: Act I: Scena finale - È tardi Giuseppe Verdi 2019-03-04 21:23:16
La Forza del Destino: Act I: Dimani si partirà Giuseppe Verdi 2019-03-04 21:21:01
La Forza del Destino: Act I: Ah, per sempre, o mio bell’angiol Giuseppe Verdi 2019-03-04 21:16:48
La Forza del Destino: Act I: Me, pellegrina ed orfana Giuseppe Verdi 2019-03-04 21:13:38
La Forza del Destino: Act I: Recitativo e romanza - Temea restasse Giuseppe Verdi 2019-03-04 21:09:58
La Forza del Destino: Act I: Introduzione, Scena - Buona notte, mia figlia Giuseppe Verdi 2019-03-04 21:08:14
La Forza del Destino: Act I: Overture Giuseppe Verdi 2019-03-04 21:05:41

“Was ist eigentlich Dein Lieblings-Song?”

Auch diese Frage lässt sich mithilfe von spotifyr beantworten - allerdings nur dann, wenn die Frage vorher nochmals präzisiert wurde: “Meinst Du meinen Lieblings-Song der letzten Wochen, Monate oder Jahre?” Mit der Funktion get_my_top_tracks() lassen sich nämlich die meistgespielten Spotify-Songs innerhalb einer gewissen Zeitspanne (“short-term”, “medium-term” oder “long-term”) ausgeben. Die Angaben, die Spotify selbst zu diesen Zeitspannen macht, sind allerdings etwas vage (siehe hier). So bezieht sich “short-term” laut Spotify “in etwa” auf die letzten vier Wochen, “medium-term” auf die letzten sechs Monate und “long-term” auf “several years”, wobei ich bei der Betrachtung meiner “long-term”-Liste das Gefühl habe, dass die letzten ein bis zwei Jahre ziemlich überproportional gewichtet werden. Aber vielleicht täuscht mein Gefühl da auch.

Nachfolgend also meine “long-term”-Lieblings-Songs, wobei ich die Auswahl auf 25 Songs beschränkt habe und neben dem jeweiligen Titel auch noch die Namen der Künstler und der jeweiligen Alben mit in die Tabelle übernommen habe.

get_my_top_tracks(time_range = 'long_term', limit = 25) %>% 
  select(track_name, artist_name, album_name) %>%
  kable() %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
track_name artist_name album_name
Florida Sleep On ASG Survive Sunrise
Helios Erebus God Is An Astronaut Helios / Erebus
No Man’s Land The Pineapple Thief Your Wilderness
Katzen Brauchen Furchtbar Viel Musik Cast - Aristocats Disney Film-Hits (Magische Musik Momente)
Chlorine & Wine Baroness Purple
If I Have To Wake Up (Would You Stop The Rain?) Baroness Purple
Arrete Leech For Better Or For Worse
Solstice If These Trees Could Talk The Bones of a Dying World
Gravity Architects All Our Gods Have Abandoned Us
What You Have Become Spidergawd Spidergawd IV
Gipfelkreuz Heisskalt Vom Stehen und Fallen
Dirty Seconds Leech For Better Or For Worse
Black Honey Thrice To Be Everywhere Is To Be Nowhere
Threatening War The Pineapple Thief Dissolution
Waiting Room Fugazi 13 Songs
In Exile The Pineapple Thief Your Wilderness
Paroli Fjørt Kontakt
Try as I Might The Pineapple Thief Dissolution
Empire of Silence While She Sleeps You Are We
Tear You Up The Pineapple Thief Your Wilderness
Heavy Scars ASG Survive Sunrise
Just Tonight Jimmy Eat World Futures (International Version)
Poison Alice Cooper The Best Of Alice Cooper
Old Heart Falls Katatonia The Fall of Hearts
The Time of Perfect Virtue Junius Days of the Fallen Sun

Und - tadaaa - mein Lieblings-Songs müsste demnach “Florida Sleep On” von ASG sein. Nun ja, den Song habe ich zwar im letzten Sommer tatsächlich hoch und runter gehört, zu meinen absoluten “Lieblings-Songs” würde ich ihn allerdings nicht zählen. Insgesamt scheint die Liste, wie bereits erwähnt, ziemlich von den letzten beiden Jahren dominiert zu sein. Das zeigt sich zum einen daran, dass sich der Top-Song der Liste auf einem Album befindet, das erst 2018 veröffentlicht wurde und zum anderen an dem ziemlich guten Ranking von “Katzen brauchen furchtbar viel Musik” - dem Lieblingslied meiner zweieinhalb-jährigen Tochter. Egal - es sind durchaus ein paar ganz coole Songs auf der Liste.

Der Vollständigkeit halber hier auch noch die “medium-term” und “short-term” Liste. Letztere ist offenkundig sehr vom neuen Album von The Intersphere geprägt…:

get_my_top_tracks(time_range = 'medium_term', limit = 25) %>% 
  select(track_name, artist_name, album_name) %>%
  kable() %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
track_name artist_name album_name
Arrete Leech For Better Or For Worse
Dirty Seconds Leech For Better Or For Worse
Antitype The Intersphere The Grand Delusion
Try as I Might The Pineapple Thief Dissolution
Death Is Not Defeat Architects Holy Hell
Threatening War The Pineapple Thief Dissolution
Permian: The Great Dying The Ocean Phanerozoic I: Palaeozoic
Lethean Katatonia Dead End Kings
Trading Shadows Night Verses From the Gallery of Sleep
Hereafter Architects Holy Hell
Cause We Didn’t Find Our Way Tuber Desert Overcrowded
White Mist The Pineapple Thief Dissolution
Die Straßen unseres Viertels Kettcar Ich vs. Wir
Mortal After All Architects Holy Hell
Devonian: Nascent The Ocean Phanerozoic I: Palaeozoic
Alien Shivers VOLA Applause Of A Distant Crowd
Tonitro Brontide Artery
Age Of Man Greta Van Fleet Anthem Of The Peaceful Army
Whaler VOLA Applause Of A Distant Crowd
Man on the Moon The Intersphere The Grand Delusion
Make a Man Estrons You Say I’m Too Much, I Say You’re Not Enough
A Million Tears Trees of Eternity Hour of the Nightingale
Katzen Brauchen Furchtbar Viel Musik Cast - Aristocats Disney Film-Hits (Magische Musik Momente)
Herbstmonster Leech For Better Or For Worse
Solstice If These Trees Could Talk The Bones of a Dying World

get_my_top_tracks(time_range = 'short_term', limit = 25) %>% 
  select(track_name, artist_name, album_name) %>%
  kable() %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
track_name artist_name album_name
Antitype The Intersphere The Grand Delusion
Shine Sylvan Home
Smoke Screen The Intersphere The Grand Delusion
New Maxim The Intersphere The Grand Delusion
The Grand Delusion The Intersphere The Grand Delusion
Madman Ashbury Endless Skies
Man on the Moon The Intersphere The Grand Delusion
Linger The Intersphere The Grand Delusion
Alien Shivers VOLA Applause Of A Distant Crowd
You Feel Better When I Feel Bad The Intersphere The Grand Delusion
Radio Rishloo Living as Ghosts With Buildings as Teeth
The Sound of Her World Sylvan Home
Dark Charade Rishloo Living as Ghosts With Buildings as Teeth
God Shuffled His Feet Crash Test Dummies God Shuffled His Feet
Mind over Matter The Intersphere The Grand Delusion
Secret Place The Intersphere The Grand Delusion
Overflow The Intersphere The Grand Delusion
Don’t Think Twice The Intersphere The Grand Delusion
Hawks on the Run ASG Survive Sunrise
Survive Sunrise ASG Survive Sunrise
Palo Alto Kettcar Palo Alto
Hard Fight Ashbury Endless Skies
Shipwreck The Intersphere The Grand Delusion
Winslow Rishloo Living as Ghosts With Buildings as Teeth
Point of No Return Sylvan Home

“…und Deine Lieblings-Band?”

Womit wir bei der Lieblings-Band wären - auch die lässt sich eruieren, wobei auch hier dieselben drei Zeitspannen angegeben werden können. Die Logik ist im Grunde dieselbe, in dem Beispiel meiner “long-Term”-Lieblingsbands unten habe ich zusätzlich zu den Bandnamen noch die Genrebezeichnungen gepackt, die Spotify den Bands so anheftet. Und die sind schon sehr witzig. Dass Kettcar beispielsweise “antideutsch” sein soll ist eine zumindest interessante Zuschreibung und Genres wie “neo-progressive”, “atmospheric post-metal” oder “orgcore”(?) sind schon zum Schmunzeln… Naja. Mit dem Ergebnis (The Pineapple Thief als mein “Top-Artist”) kann ich zwar irgendwie leben, auch hier zeigt sich allerdings, dass Daten aus den letzten ein bis zwei Jahren vermutlich überproportional gewichtet werden. Sei’s drum - ein interessanter Einblick in meine Spotify-Daten eröffnet sich dadurch allemal.

get_my_top_artists(time_range = 'long_term', limit = 20) %>% 
  select(artist_name, artist_genres) %>% 
  rowwise %>% 
  mutate(artist_genres = paste(artist_genres, collapse = ', ')) %>% 
  ungroup %>%
  kable() %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
artist_name artist_genres
The Pineapple Thief art rock, neo-progressive, progressive metal, progressive rock, symphonic rock
Architects mathcore, melodic metalcore, metalcore, screamo
Kettcar antideutsche, german indie, german pop, german punk, german rock, liedermacher
Katatonia doom metal, gothic metal, melodic death metal, metal, pagan black metal, progressive metal, swedish metal
The Dear Hunter dreamo, progressive post-hardcore
Opeth alternative metal, death metal, groove metal, melodic death metal, metal, progressive metal, rock, swedish metal
Ghost metal
God Is An Astronaut instrumental post-rock, post-rock
Fjørt deep german punk
Thrice emo, modern rock, pop punk, post-hardcore, screamo
ASG psychedelic doom, retro metal, sludge metal, stoner metal, stoner rock
Long Distance Calling german post-rock, instrumental post-rock, post-metal, post-rock
Propagandhi canadian indie, canadian punk, folk punk, melodic hardcore, orgcore, punk, ska punk, skate punk
Hot Water Music emo, emo punk, melodic hardcore, orgcore, pop punk, post-hardcore, punk, skate punk
Leech atmospheric post-rock, german post-rock, instrumental post-rock, post-rock
The Ocean alternative metal, atmospheric post-metal, avantgarde metal, djent, jazz metal, mathcore, post-doom metal, post-metal, post-rock, progressive metal, sludge metal
O’Brother dreamo, progressive post-hardcore
A Perfect Circle alternative metal, alternative rock, modern rock, nu metal, post-grunge, rap rock, rock
TesseracT djent, jazz metal, progressive metal
Irie Révoltés antideutsche, french reggae, german reggae, german rock
Sebastian Kuhn
Sebastian Kuhn
Politikwissenschaftler & Soziologe im Gesundheitswesen

Ähnliches