Data Science, nawet w muzyce.
Testując Spotify API znalazłem wiele funkcji ukrytych za piosenkami, których słuchamy na co dzień.
Oto projekt, ale wolę pokazać go w tym artykule.https://github.com/ivanurquiza/Spotify-Analysis
Wpadłem na pomysł przeanalizowania najczęściej słuchanych w tej chwili piosenek.
Należy odpowiedzieć na dwa główne pytania:
1. Co jest charakterystyczne dla popularnej muzyki?
2. Czym różni się od muzyki staroświeckiej?
# FILL IN THESE VALUES WITH YOUR OWN KEYS
client_id = ...
client_secret = ...
# Make sure to add this on "Edit Settings" in your Dashboard
redirect_uri = "http://localhost:9000"
import spotipy
from spotipy.oauth2 import SpotifyOAuth
# Connect with API Keys created earlier
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri))
Musiałem dokonać wyboru. W tym przypadku wykorzystałem bardzo znaną w Argentynie playlistę stworzoną przez Spotify, która zawiera 50 najczęściej słuchanych utworów w tej chwili:
#Playlist ID
TOP50_playlist = sp.playlist('37i9dQZEVXbMMy2roB9myp')
for track_data in TOP50_playlist['tracks']['items']:
#Getting just the ID (last part of the url)
track_id = track_data['track']['uri'].split(':')[-1]
track_name = track_data['track']['name']
track_popularity = track_data['track']['popularity']
list_tracksids.append((track_name,track_id,track_popularity))
df_features = pd.DataFrame()
for idx, dict_trackfeatures in enumerate(sp.audio_features(tracks=[url[1] for url in list_tracksids])):
dict_trackfeatures['track_name'] = list_tracksids[idx][0]
dict_trackfeatures['popularity'] = list_tracksids[idx][2]
df_features = pd.concat([df_features,pd.Series(dict_trackfeatures)], axis=1)
#Selects only useful features
df_features=df_features.transpose()[['track_name','popularity','danceability','energy','loudness','speechiness','acousticness','instrumentalness','liveness','tempo']]
#Display Top 5 songs
df_features.head()
Jesteśmy gotowi. Przeanalizujmy dane!
Narysujmy kilka wykresów, aby uzyskać pierwsze wzorce dotyczące najpopularniejszej muzyki.
Z wykresu po lewej stronie widać, że muzyka, która składa się na naszą playlistę TOP 50, znajduje się głównie w drugiej połowie (ponad 0,5 z 1), co najwyraźniej oznacza, że jest bardzo taneczna. Skąd możemy wiedzieć, czy to podejrzenie jest prawdziwe?
Porównajmy średnią taneczność tych utworów z muzyką klasyczną. Witaj Mozarcie!
import seaborn as sns
import matplotlib.pyplot as plt
# Let's plot some charts for getting the first patterns about the most popular music
sns.set_theme(context='notebook',style="ticks")
fig, axes = plt.subplots(1, 2, figsize=(10,5))
# Left - Danceability's histogram with kde
sns.distplot(ax=axes[0], x=df_features["danceability"], bins=6, kde=True, color="#5B3BA0")
axes[0].set(xlabel='Danceability', ylabel='Frequency')
axes[0].set_title('TOP 50 Danceability freq.')
# Right - Comparation between the playlist avarage and Mozart's most popular song
# Requiem, K. 626: Lacrimosa
mozart_danceability = sp.audio_features(tracks=['3oHSL6pt9LpNrQZuQGu9wL'])[0]['danceability']
avg_top50_danceability = df_features['danceability'].mean()
sns.barplot(ax= axes[1],
x = 'who',
y = 'Danceability',
data = {'who':['TOP 50','MOZART'],
'Danceability':[avg_top50_danceability, mozart_danceability]},
palette=['#5B3BA0','#A378FF']
)
axes[1].set(ylabel='Danceability')
axes[1].set_title('Mozart vs TOP 50')
plt.show()
Jak możemy sobie wyobrazić, Mozarta nie ma na liście 50 najczęściej odtwarzanych utworów. W oparciu o naszą krótką analizę, Mozart może nie mieć wystarczających zdolności tanecznych, aby znaleźć się na liście odtwarzania.
- Taneczność Mozarta: 0,162
- Średnia taneczności TOP 50: 0,739
#Adding Mozart's song variables to our dataframe
mozart = pd.DataFrame({'track_name':['Mozart'], 'popularity':[0.0]})
for k,v in sp.audio_features(tracks=['3oHSL6pt9LpNrQZuQGu9wL'])[0].items():
if k in df_features.keys():
mozart[k]=v
df_features = pd.concat([df_features,mozart], axis=0)
df_features['playlist'] = ['TOP 50' if x != 'Mozart' else 'Mozart' for x in df_features['track_name']]
df_features.tail(1)
#Scatter plot
plt.figure(dpi=80)
sns.scatterplot(
data=df_features, x='acousticness',y='loudness', hue="playlist",
sizes=(20, 200), legend="full", palette=['#5B3BA0','#D00000']
)
plt.show()
Ten wykres częściowo pomaga zrozumieć, dlaczego Mozart nie jest modny. Utwory w Top 50 mają zbliżone wartości zmiennych „głośność” i „akustyka” i są silnie skoncentrowane w lewej górnej części wykresu. Trend jest wyraźny: wysoka głośność i niski poziom akustyki. Z drugiej strony Mozart idzie wbrew trendowi!
Te same kroki, inna lista odtwarzania
A gdyby zamiast Mozarta i modnych piosenek wziąć playlistę z najlepszymi utworami lat 80.?
Zróbmy to samo, ale trochę inaczej.
AllOut80s = sp.playlist('37i9dQZF1DX4UtSsGT1Sbe')
list_tracksids = list()
for track_data in AllOut80s['tracks']['items']:
#Gets just the ID (last part of the url)
track_id = track_data['track']['uri'].split(':')[-1]
track_name = track_data['track']['name']
track_popularity = track_data['track']['popularity']
list_tracksids.append((track_name,track_id,track_popularity))
AllOut80s_features = pd.DataFrame()
for idx, dict_trackfeatures in enumerate(sp.audio_features(tracks=[url[1] for url in list_tracksids])):
dict_trackfeatures['track_name'] = list_tracksids[idx][0]
dict_trackfeatures['popularity'] = list_tracksids[idx][2]
AllOut80s_features = pd.concat([AllOut80s_features,pd.Series(dict_trackfeatures)], axis=1)
#Selects only useful features
AllOut80s_features=AllOut80s_features.transpose()[['track_name','popularity','danceability','energy','loudness','speechiness','acousticness','instrumentalness','liveness','tempo']]
AllOut80s_features['playlist'] = 'AllOut80s'
#Handles data types
AllOut80s_features[['danceability','energy','loudness','speechiness','acousticness','instrumentalness','liveness','tempo']]=AllOut80s_features[['danceability','energy','loudness','speechiness','acousticness','instrumentalness','liveness','tempo']].astype(float)
Zobacz wyniki:
# Setting up concatenated df
df_allsongs = pd.concat([df_features, AllOut80s_features[:50]]).reset_index()
df_allsongs= df_allsongs.drop(df_allsongs.index[df_allsongs['playlist'] == 'Mozart'])
plt.figure(dpi=80)
sns.lmplot(
data=df_allsongs, x='acousticness',y='loudness', hue="playlist",
legend="full", palette=['#5B3BA0','#D00000']
)
plt.show()
Patrząc na rozkłady i linie regresji dla każdej playlisty, zauważamy, że trendy są zupełnie inne. Chociaż związek między zmiennymi (nachylenie krzywych) pozostaje dość podobny, utwory wydają się być ułożone we wzór, a playlista Top 50 ma wyższy poziom „głośności”.
Wystarczy przyjrzeć się tym dwóm cechom, by przekonać się, że muzyka lat 80. jest bardziej zbliżona do aktualnych trendów niż Mozart.
Pójdźmy z projektem o krok dalej!
Czy możemy przewidzieć, biorąc pod uwagę wszystkie możliwe zmienne, do której playlisty należy utwór? Nie jestem pewien, ale odpowiedź brzmi prawdopodobnie KNeighbours .
Wyszukałem w Google najbardziej reprezentatywną piosenkę z lat 80., aby użyć jej jako danych wejściowych do naszej prognozy modelowania:
Features used for modeling
featlist=['danceability','energy','loudness','speechiness','acousticness','instrumentalness','liveness','tempo']
prince = {}
for k,v in sp.audio_features(tracks=['54X78diSLoUDI3joC2bjMz'])[0].items():
if k in featlist:
prince[k]=v
prince = pd.DataFrame(prince.items()).transpose()
prince.columns = prince.iloc[0]
prince=prince[1:]
prince[featlist] = prince[featlist].astype(float)
prince
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
X = df_allsongs[featlist]
y = df_allsongs['playlist']
knn.fit(X,y)
# Prediction
prediction = knn.predict(prince)
print('The song could be included in the playlist: ', prediction[0])
Dziękuje za przeczytanie!
Kontakt : www.linkedin.com/in/ivanroblesurquiza
Twitter :https://twitter.com/urqivo

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































