Анализ с использованием аудиофункций Spotify
Я буду просматривать плейлисты еженедельных песенных чартов, которые создаются Spotify каждую неделю и к которым легко получить доступ. Они состоят из 50 самых популярных треков в стране или во всем мире.
Меня больше всего интересовали списки воспроизведения песен в Южной Африке, Южной Корее, США и Индии, и я выбрал их для своего анализа.
Вы можете посмотреть другие страны, исходя из ваших конкретных интересов. Все, что вам нужно для конкретного плейлиста, — это его соответствующий идентификатор, который доступен в разделе просмотра рабочего стола Spotify: Charts → Еженедельные песенные чарты в Spotify. И чтобы выбрать id, вам просто нужно скопировать id из ссылки этого плейлиста. Здесь, в приведенном ниже примере, идентификатором будет выделенная жирным шрифтом комбинация некоторых цифр и букв.
https://open.spotify.com/playlist/37i9dQZEVXbLp5XoPON0wI
import sys import warnings if not sys.warnoptions: warnings.simplefilter("ignore") import spotipy import json import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from math import pi from scipy.cluster.hierarchy import dendrogram, linkage from sklearn.preprocessing import MinMaxScaler from spotipy.oauth2 import SpotifyClientCredentials sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials(client_id="######", client_secret="####")) def compare_playlist(playlist_id): results = sp.playlist(playlist_id) ids=[] for item in results['tracks']['items']: track = item['track']['id'] ids.append(track) #ids song_name=[] for item in ids: song_name_ = sp.track(item)['name'] song_name.append(song_name_) # check the song feature features = sp.audio_features(ids) # change dictionary to dataframe features_df=pd.DataFrame.from_dict(features) # combine two list + features song_demo = pd.DataFrame({'id': ids,'song_name': song_name}) final_df=song_demo.merge(features_df) return(final_df) feat_df_Skorea = compare_playlist("37i9dQZEVXbJZGli0rRP3r") feat_df_Safrica = compare_playlist("37i9dQZEVXbJV3H3OfCN1z") feat_df_usa = compare_playlist("37i9dQZEVXbLp5XoPON0wI") feat_df_india = compare_playlist("37i9dQZEVXbMWDif5SCBJq") feat_df_global = compare_playlist("37i9dQZEVXbMDoHDwVN2tF")
Что говорит Дарт Радар?
Для обзора аудиофункций Spotify и того, как они отображаются в разных плейлистах, я использую радарную диаграмму.
from sklearn import preprocessing feat_cols = ['danceability', 'energy', 'speechiness', 'acousticness', 'instrumentalness', 'liveness', 'valence'] mean_vals = pd.DataFrame(columns=feat_cols) mean_vals = mean_vals.append(feat_df_Skorea.median(), ignore_index=True) mean_vals = mean_vals.append(feat_df_Safrica.median(), ignore_index=True) mean_vals = mean_vals.append(feat_df_usa.median(), ignore_index=True) mean_vals = mean_vals.append(feat_df_india.median(), ignore_index=True) import plotly.graph_objects as go import plotly.offline as pyo fig = go.Figure( data=[ go.Scatterpolar(r=mean_vals.iloc[0], theta=feat_cols, fill='toself', name='South Korea'), go.Scatterpolar(r=mean_vals.iloc[1], theta=feat_cols, fill='toself', name='South Africa'), go.Scatterpolar(r=mean_vals.iloc[2], theta=feat_cols, fill='toself', name='USA'), go.Scatterpolar(r=mean_vals.iloc[3], theta=feat_cols, fill='toself', name='India'), ], layout=go.Layout( title=go.layout.Title(text='Feature comparison'), polar={'radialaxis': {'visible': True}}, showlegend=True ) ) fig.write_image(file='RadarChart.png', format='png') fig.show()
Как вы можете видеть, на приведенном ниже графике показано распределение различных атрибутов плейлиста. «0» каждой оси — это центр колеса, и атрибут становится все выше и выше по мере того, как мы удаляемся от центра.
Идеальную оценку танцевальности можно увидеть в плейлисте для Южной Африки. Они должны хорошо танцевать!
Танцевальность описывает, насколько трек подходит для танцев, основываясь на сочетании музыкальных элементов, включая темп, стабильность ритма, силу удара и общую регулярность. Значение 0,0 соответствует наименее танцевальному, а значение 1,0 — наиболее танцевальному.
Индия лидирует с точки зрения акустики. А самая высокая валентность и энергия наблюдается в Южной Корее.
Валентность — это показатель от 0,0 до 1,0, описывающий музыкальную позитивность, передаваемую треком. Треки с высокой валентностью звучат более позитивно (например, счастливые, веселые, эйфорические), в то время как треки с низкой валентностью звучат более негативно (например, грустные, подавленные, злые).
Энергия представляет собой меру от 0,0 до 1,0 и представляет перцептивную меру интенсивности и активности. Как правило, энергичные треки кажутся быстрыми, громкими и шумными. Например, у дэт-метала высокая энергия, а у прелюдии Баха низкий балл по шкале. Характеристики восприятия, влияющие на этот атрибут, включают динамический диапазон, воспринимаемую громкость, тембр, скорость начала и общую энтропию.
Как и ожидалось, живость и речьнизки, что подтверждает, что песни в этих плейлистах не записывались во время исполнения. live и включает в себя музыкальные / неречевые треки.
А как насчет других функций?
Я пропустил некоторые функции, так как хотел посмотреть на них отдельно от радиолокационной диаграммы. Кроме того, их масштаб был другим, и было бы неплохо их нормализовать (например, тональность).
feat_df_Skorea["Playlist_name"] = "South Korea" feat_df_Safrica["Playlist_name"] = "South Africa" feat_df_usa["Playlist_name"] = "USA" feat_df_india["Playlist_name"] = "India" res = pd.concat([feat_df_Skorea,feat_df_Safrica,feat_df_usa,feat_df_india]) #Creating a function for density plot for other left out features - def feature_densityPlt(feature): playlist_names = ['South Korea', 'South Africa', 'USA','India'] # Iterate through the 4 playlist for playlist_name in playlist_names: # Subset to the playlist subset = res[res['Playlist_name'] == playlist_name] # Draw the density plot sns.distplot(subset[feature], hist = False, kde = True, kde_kws = {'linewidth': 3}, label = playlist_name) # Plot formatting plt.legend(prop={'size': 9}, title = 'playlist_names') plt.title('Density Plot for '+feature+' across different countries playlists') plt.xlabel(feature) plt.savefig('DensityPlot_'+feature+'.png')
- Ключ
feature_densityPlt('key')
Наиболее интересное распространение имеет США. Топ-50 песен в США имеют разнообразное распространение, и ни одна любимая тональность не может быть оценена. Для других стран мы наблюдаем бимодальное распределение.
Всего в 4 странах популярны два ключа — 1(C♯/D♭) и 10(A♯, B♭).
Примечание можно определить, сопоставив числа со стандартной нотацией класса высоты тона.
2. Темп
feature_densityPlt('tempo')
ЮАР выделялась выше. В 50 лучших песнях Южной Африки частота составляет около 110 ударов в минуту. Для других плейлистов мы можем наблюдать бимодальное распределение — один пик наблюдается около 110 ударов в минуту, а другой — около 160 ударов в минуту.
3. Громкость
Общая громкость дорожки в децибелах (дБ). Значения громкости усредняются по всей дорожке и полезны для сравнения относительной громкости дорожек. Громкость – это качество звука, которое является основным психологическим коррелятом физической силы (амплитуды). Обычно значения находятся в диапазоне от -60 до 0 дБ.
feature_densityPlt('loudness')
Южная Африка и Индия немного более разнообразны с точки зрения громкости по сравнению с Южной Кореей и США, которые в основном сосредоточены вокруг (-8,-2) дБ.
4. Валентность
feature_densityPlt('valence')
Очевидно, что Южная Корея имеет больше позитива в своих 50 лучших песнях по сравнению с другими тремя странами.
5. Акустика
feature_densityPlt('acousticness')
Приведенный выше график плотности подтверждает наш предыдущий вывод о том, что 50 лучших песен Индии более акустичны по своей природе и насколько они разнообразны по сравнению с ними. Южная Африка заметно менее акустична.
А как же Венн и Джерри?
import matplotlib matplotlib.use('Agg') import venn set_Skorea = set(feat_df_Skorea["song_name"]) set_Safrica = set(feat_df_Safrica["song_name"]) set_usa = set(feat_df_usa["song_name"]) set_india = set(feat_df_india["song_name"]) labels = venn.get_labels([set_Skorea, set_Safrica, set_usa, set_india], fill = ['number']) fig, ax = venn.venn4(labels, names=['South Korea', 'South Africa', 'USA', 'India']) #fig.write_image(file='VennDiagram.png', format='png') fig.savefig('VennDiagram.png') fig.show()
Было 4 песни, которые были общими для всех плейлистов:
set_usa.intersection(set_Skorea, set_Safrica,set_india) {'As It Was', 'Glimpse of Us', 'Left and Right (Feat. Jung Kook of BTS)', 'STAY (with Justin Bieber)'}
Тепловая карта корреляции
A) Для еженедельного глобального плейлиста
feat_global_num = feat_df_global.select_dtypes(include=[np.float]) plt.figure(figsize=(16,8)) sns.heatmap(feat_global_num.corr(),cmap='mako') plt.savefig('CorrHeatmap_globalPlaylist.png') plt.show()
Здесь отчетливо видна отрицательная корреляция между двумя парами — танцевальностью и темпом; Энергия и акустика. Между тем, между энергией и громкостью наблюдается положительная корреляция, что также имеет смысл.
Б) Для сравнения плейлистов в разных странах
feat_Skorea_num = feat_df_Skorea.select_dtypes(include=[np.float]) feat_Safrica_num = feat_df_Safrica.select_dtypes(include=[np.float]) feat_usa_num = feat_df_usa.select_dtypes(include=[np.float]) feat_india_num = feat_df_india.select_dtypes(include=[np.float]) res_num = res.select_dtypes(include=[np.float]) f,(ax1,ax2,ax3, ax4, axcb) = plt.subplots(1,5, figsize=(25,10), gridspec_kw={'width_ratios':[1,1,1,1,0.08]}) ax1.get_shared_y_axes().join(ax2,ax3) g1 = sns.heatmap(feat_Skorea_num.corr(),cmap='mako',cbar=False,ax=ax1) g1.set_title('South Korea', fontsize=20) g1.set_ylabel('') g1.set_xlabel('') g2 = sns.heatmap(feat_Safrica_num.corr(),cmap='mako',cbar=False,ax=ax2) g2.set_title('South Africa', fontsize=20) g2.set_ylabel('') g2.set_xlabel('') g2.set_yticks([]) g3 = sns.heatmap(feat_usa_num.corr(),cmap='mako',ax=ax3, cbar_ax=axcb) g3.set_title('USA', fontsize=20) g3.set_ylabel('') g3.set_xlabel('') g3.set_yticks([]) g4 = sns.heatmap(feat_india_num.corr(),cmap='mako',ax=ax4, cbar_ax=axcb) g4.set_title('India', fontsize=20) g4.set_ylabel('') g4.set_xlabel('') g4.set_yticks([]) # rotate the ticklabels correctly: for ax in [g1,g2,g3,g4]: tl = ax.get_xticklabels() ax.set_xticklabels(tl, rotation=90) tly = ax.get_yticklabels() ax.set_yticklabels(tly, rotation=0) plt.savefig('CorrHeatmap_acrossDiffPlaylists.png') plt.show()
В целом тепловые карты корреляции Южной Кореи и Индии больше похожи друг на друга, тогда как Южная Африка и США также не сильно отличаются друг от друга с точки зрения характеристик звука. Это также было видно на графике радара выше.
Танцевальность положительно коррелирует с энергичностью и громкостью в Южной Корее и Индии (0,4–0,6). Речь также положительно коррелирует с энергией в Южной Корее и Индии, но не сильно в других странах. Другой интересной особенностью является валентность и то, как можно увидеть высокую положительную корреляцию между валентностью и танцевальностью в тех 2 странах, где на самом деле это не так, как в США или Южной Африке.
Плейлист Южной Африки немного отличается от других плейлистов. Танцевальность отрицательно коррелирует с акустикой и живостью (это не наблюдается в других странах или во всем мире); точно так же мы не видим большой отрицательной корреляции между акустикой и энергией.
Положительная корреляция между громкостью и энергией одинакова в разных странах (это согласуется с глобальным плейлистом).
Это все, что у меня есть для этого поста! Дайте мне знать, если у вас есть какие-либо другие предложения или интерпретации.
Вы также можете найти мой код на моей странице github здесь.
Для начинающих API Spotify вы можете проверить эту ссылку. Пожалуйста, пингуйте меня, если вы в конечном итоге анализируете плейлисты других стран / регионов!
Я также написал аналогичный пост для анализа собственных плейлистов, если интересно, нажмите здесь.
Интересный факт — вы можете аплодировать до 50 раз за пост или список на медиуме, чтобы показать поддержку автору :)