Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
「国と音楽」 ~spotifyrを用いて~ #muana
Search
bob3bob3
October 28, 2023
Science
2
570
「国と音楽」 ~spotifyrを用いて~ #muana
SpotifyのWebAPIから取得できるデータを使い、国ごとに流行っている曲の傾向やグループ分けを行ってみた。
#muana #R言語 #rstats
bob3bob3
October 28, 2023
Tweet
Share
More Decks by bob3bob3
See All by bob3bob3
RでPSM分析
bob3bob3
1
270
Rでコンジョイント分析 2024年版
bob3bob3
0
1.3k
『改訂新版前処理大全』の話と Apache Parquet の話 #TokyoR
bob3bob3
0
1.1k
R言語の環境構築と基礎 Tokyo.R 112
bob3bob3
0
560
『データ可視化学入門』をPythonからRに翻訳した話(増強版)
bob3bob3
0
500
『データ可視化学入門』を PythonからRに翻訳した話
bob3bob3
1
580
qeMLパッケージの紹介
bob3bob3
0
2k
パーマーステーションのペンギンたち#3 探索的データ分析(EDA)編
bob3bob3
1
720
Redditで遊ぼう #TokyoR 106
bob3bob3
0
730
Other Decks in Science
See All in Science
白金鉱業Meetup Vol.16_数理最適化案件のはじめかた・すすめかた
brainpadpr
3
1.8k
Iniciativas independentes de divulgação científica: o caso do Movimento #CiteMulheresNegras
taisso
0
1.5k
ガウス過程回帰とベイズ最適化
nearme_tech
PRO
1
410
Factorized Diffusion: Perceptual Illusions by Noise Decomposition
tomoaki0705
0
390
機械学習 - 授業概要
trycycle
PRO
0
190
機械学習 - SVM
trycycle
PRO
1
820
地質研究者が苦労しながら運用する情報公開システムの実例
naito2000
0
190
MoveItを使った産業用ロボット向け動作作成方法の紹介 / Introduction to creating motion for industrial robots using MoveIt
ry0_ka
0
480
高校生就活へのDA導入の提案
shunyanoda
0
190
mathematics of indirect reciprocity
yohm
1
140
眼科AIコンテスト2024_特別賞_6位Solution
pon0matsu
0
400
生成AI による論文執筆サポートの手引き(ワークショップ) / A guide to supporting dissertation writing with generative AI (workshop)
ks91
PRO
0
500
Featured
See All Featured
Six Lessons from altMBA
skipperchong
28
3.8k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
20
1.3k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Docker and Python
trallard
44
3.4k
Practical Orchestrator
shlominoach
188
11k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.3k
VelocityConf: Rendering Performance Case Studies
addyosmani
329
24k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
Thoughts on Productivity
jonyablonski
69
4.7k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
It's Worth the Effort
3n
184
28k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Transcript
音楽と国 ~spotifyrを用いて~ Music×Analytics Meetup Vol.11 (2023/10/28) @bob3bob3
Spotify
Spotifyとは? Spotify(スポティファイ)は、スウェーデンの 企業スポティファイ・テクノロジーによって運 営されている音楽ストリーミングサービス。 (Wikipediaより引用)
spotifyr • R言語のspotifyrパッケージを使って、SpotifyのWeb APIから楽曲や アルバム、アーティストなどの情報を一括で取得。 • spotifyrで取得できる情報の一例 ◦ アルバム単位 ▪
ジャケット画像、曲数、アルバム名、リリース日、人気度など ◦ アーティスト単位 ▪ ジャンル、関連するアーティスト、人気度など ◦ 楽曲単位 ▪ アコースティック度、ダンス度、インスト度、音圧、テンポ、キー、人気度な ど ◦ 詳しくはspotifyのwebAPIのページを参照のこと。
プレイリスト • Spotifyにはプレイリストという機能が あります。好きな曲をまとめて公開す る機能です。 • Spotify公式のプレイリストもあって、 例えば各国のTop50がプレイリストと して公開されていたりします。 •
これもspotifyrで扱えて、プレイリスト ごとに含まれる楽曲のデータなどを抽 出できます。
やってみよう! • 「各国のTop50のプレイリストから、 含まれる楽曲を抽出し、各楽曲の 特徴を用いて各国をクラスタリング する。」というのをやってみます。 • 事前準備としてSpotifyのアカウント と開発者アカウントの登録が必要で す。
• 2023年07月14日時点のデータで す。
# パッケージ読み込み library(conflicted) #関数の衝突防止 library(tidyverse) #モダンなデータ処理 library(spotifyr) #Spotifyの Web API
操作 # 開発者アカウント認証 Sys.setenv(SPOTIFY_CLIENT_ID = 'xxxxxxxxxx') Sys.setenv(SPOTIFY_CLIENT_SECRET = 'xxxxxxxxxx') access_token <- get_spotify_access_token() 準備
# プレイリスト検索 res_search <- search_spotify( q = 'top50', type =
'playlist', limit = 50 ) |> dplyr::filter(owner.id == "spotify") |> #公式プレイリストに絞る select(name, id) |> #列を絞る mutate(name = name |> str_remove("Top 50 - ")) |> #プレイリスト名の整形 dplyr::filter( #ノイズになる行を削除 !(name %in% c("Global", "Greatest Hip-Hop Beats of All Time")) ) |> rowid_to_column() #ID番号を振る Top50のプレイリストを検索
検索結果 国名とプレイリストの id。
playlists_tracks <- res_search |> pull(id) |> map( #各プレイリストに含まれる楽曲を抽出 \(id) get_playlist_tracks(id)
|> select(track.id, track.name), .progress = TRUE ) |> list_rbind(names_to = "rowid") Top50のプレイリストから各楽曲のIDを検索
プレイリストに含まれる楽曲のリスト
各楽曲の分析情報を取得 res_track <- playlists_tracks |> pull(track.id) |> unique() |> map(
\(track.id) get_track_audio_features(track.id), .progress = TRUE ) |> list_rbind() |> right_join( playlists_tracks |> left_join(res_search, by = join_by(rowid)), by = join_by(id == track.id) ) |> mutate( duration_s = duration_ms / 1000, # ミリ秒を秒に country = as.factor(name) ) |> select( country, duration_s, energy, acousticness, liveness, speechiness, valence, danceability, tempo, id, track.name)
各楽曲の分析情報を取得
各楽曲の分析情報を取得 • duration_ms: 曲の長さ(ミリ秒) • energy: 0~1。騒がしい曲か静かな曲か。 • acousticness: アコースティック度合。電気的に増幅されている程度。
• liveness: 0~1。ライブ音源かスタジオ音源か。 • speechiness: 0~1。歌ではない話し言葉の量。 • valence: 0~1。ポジティブさ。 • danceability: 0~1。踊りやすさ。 • tempo: テンポ(BPM)。
各楽曲の分析情報
分析情報に関する発表事例
EDA library(summarytools) res_track |> select(!c(country, id, track.name)) |> dfSummary() |>
summarytools::view()
EDA library(GGally) res_track |> select(!c(country, id, track.name)) |> ggpairs(aes(alpha =
0.1))
国ごとの違い res_track2 |> ggplot( aes( x = reorder( country, duration_s,
FUN = median), y = duration_s)) + geom_boxplot() + coord_flip() + labs(x = "国", y = "演奏時間(秒)") + theme(text = element_text(size = 12))
クラスタリングしよう! # 国ごとに中央値を算出し、さらに標準化する median_by_country <- res_track |> select(!c(id, track.name)) |>
group_by(country, .drop = FALSE) |> summarise(across(everything(), median)) |> column_to_rownames(var = "country") |> scale() # 階層型クラスタリング library(factoextra) library(dendextend) cluster_tree <- median_by_country |> dist() |> hclust(method = "ward.D2") cluster_tree |> fviz_dend( k=6, cex=0.5, horiz = TRUE, label_cols = "black", k_colors = c( "#ff4b00", "#990099", "#03af7a", "#005aff", "#804000", "#ff8082"), rect = TRUE, rect_fill = TRUE, rect_border = 8 )
地図! clusters <- tibble( country = median_by_country |> rownames(), cluster
= cluster_tree |> cutree(k=6) ) library(ggrepel) library(sf) library(rnaturalearth) world_map <- ne_countries( scale = "small", returnclass = "sf" ) |> left_join( clusters |> mutate( country = country |> str_replace("USA", "United States") |> str_replace("South Korea", "Republic of Korea") ), by=join_by(name_long == country) ) world_map |> ggplot() + geom_sf(aes(fill = as.factor(cluster))) + theme_light() + labs(fill = "cluster") + scale_colour_brewer(palette = "Dark2")
None
Enjoy! 次回「2010年代 King Crimson のセットリスト分析」でお会いしま しょう!