spotify

Author

Takafumi Kubota

Abstract

This analysis investigates the relationships between various musical features of songs using a dataset containing attributes such as Danceability, Energy, Key, Loudness, and more. We calculated the mean, standard deviation, and five-number summary for each variable. Correlation matrices were computed, and the most strongly correlated pairs were identified. Boxplots and scatterplot matrices were generated to visualize distributions and correlations. Key findings include a strong negative correlation between Key and Energy, and strong positive correlations between Liveness and Acousticness, and Tempo and Liveness.

Keywords

Basic Analysis, Boxplot, Scatterplot Matrix, Correlation Analysis, Data Visualization, Music Features, Statistical Summary

1 Full Code (R)

Code
# 必要なパッケージの読み込み
library(ggplot2)
library(reshape2)
library(dplyr)
library(psych)

# データの読み込み
songs_data <- read.csv("songs_data.csv")

# 平均値と標準偏差の計算
mean_values <- colMeans(songs_data[, sapply(songs_data, is.numeric)])
std_values <- apply(songs_data[, sapply(songs_data, is.numeric)], 2, sd)

# 5数要約の計算
fivenum_values <- t(apply(songs_data[, sapply(songs_data, is.numeric)], 2, fivenum))

# 平均値、標準偏差、5数要約をデータフレームにまとめる
summary_df <- data.frame(
  Mean = mean_values,
  SD = std_values,
  Min = fivenum_values[, 1],
  Q1 = fivenum_values[, 2],
  Median = fivenum_values[, 3],
  Q3 = fivenum_values[, 4],
  Max = fivenum_values[, 5]
)

# 結果を表示
print(summary_df %>%
        mutate(across(where(is.numeric), ~ round(., 3))))
                      Mean     SD    Min      Q1  Median      Q3     Max
ダンス性             0.590  0.105  0.425   0.551   0.587   0.649   0.736
エネルギー           0.799  0.117  0.680   0.695   0.755   0.935   0.941
キー                 3.800  2.860  1.000   1.000   3.000   6.000   9.000
大声度              -4.742  1.305 -6.490  -6.215  -4.659  -3.711  -2.783
音楽のモード         0.900  0.316  0.000   1.000   1.000   1.000   1.000
音楽のスピーチ       0.053  0.026  0.029   0.033   0.045   0.054   0.105
アコースティック度   0.065  0.070  0.002   0.010   0.033   0.112   0.199
楽器演奏度           0.000  0.000  0.000   0.000   0.000   0.000   0.000
生活性               0.247  0.136  0.052   0.118   0.248   0.331   0.481
ヴァレンス           0.641  0.188  0.292   0.524   0.679   0.784   0.836
テンポ             126.849 28.846 98.048 106.382 114.001 150.015 180.002
拍子記号             3.900  0.316  3.000   4.000   4.000   4.000   4.000
Code
# 変数名の英訳
colnames(songs_data) <- c("Title", "Danceability", "Energy", "Key", "Loudness", "Mode", 
                          "Speechiness", "Acousticness", "Instrumentalness", "Liveness", 
                          "Valence", "Tempo", "TimeSignature")

# データの整形
melted_data <- melt(songs_data, id.vars = "Title")

# 箱ひげ図の作成
ggplot(melted_data, aes(x = variable, y = value)) + 
  geom_boxplot(fill = "skyblue", color = "black") + 
  theme_minimal() + 
  labs(title = "Boxplot of Variables", x = "Variable", y = "Value") + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) + 
  facet_wrap(~ variable, scales = "free", ncol = 3)

Code
# 変数名の英訳
colnames(songs_data) <- c("Title", "Danceability", "Energy", "Key", "Loudness", "Mode", 
                          "Speechiness", "Acousticness", "Instrumentalness", "Liveness", 
                          "Valence", "Tempo", "TimeSignature")

# 数値データのみ抽出
numeric_data <- songs_data %>% select(where(is.numeric))

# 散布図行列の描画
pairs.panels(numeric_data, 
             method = "pearson",  # 相関係数の種類
             hist.col = "skyblue", # ヒストグラムの色
             density = TRUE,      # 密度プロットの追加
             ellipses = TRUE      # 信頼楕円の追加
)

Code
# 相関行列を計算
cor_matrix <- cor(numeric_data, use = "complete.obs")

# 相関行列を長い形式に変換
cor_long <- as.data.frame(as.table(cor_matrix))

# 対角要素を除外
cor_long <- cor_long %>% filter(Var1 != Var2)

# 相関係数の絶対値が大きい順にソート
cor_long <- cor_long %>% mutate(abs_value = abs(Freq)) %>% arrange(desc(abs_value))

# 重複のないように変数ペアを選択
selected_pairs <- cor_long %>%
  distinct(Var1, Var2, .keep_all = TRUE) %>%
  slice(1:6)

# 選択された変数を抽出
selected_vars <- unique(c(selected_pairs$Var1, selected_pairs$Var2))
selected_data <- numeric_data %>% select(all_of(selected_vars))

# 散布図行列の描画
pairs.panels(selected_data, 
             method = "pearson",  # 相関係数の種類
             hist.col = "skyblue", # ヒストグラムの色
             density = TRUE,      # 密度プロットの追加
             ellipses = TRUE      # 信頼楕円の追加
)

1.1 コードの説明

  1. パッケージの読み込み:

    • ggplot2: データの視覚化に使用されるパッケージです。

    • reshape2: データの変形を行うためのパッケージです。

    • dplyr: データ操作に便利なパッケージです。

    • psych: 散布図行列の作成に使用する心理統計パッケージです。

  2. データの読み込み:

    • read.csv("songs_data.csv")を使って、CSVファイルからデータを読み込みます。
  3. 平均値と標準偏差の計算:

    • colMeans(songs_data[, sapply(songs_data, is.numeric)]):

      • 各数値列の平均値を計算します。

      • sapply(songs_data, is.numeric)は、数値列のみを選択します。

    • apply(songs_data[, sapply(songs_data, is.numeric)], 2, sd):

      • 各数値列の標準偏差を計算します。

      • apply関数の第2引数2は列に対して操作を行うことを示します。

  4. 5数要約の計算:

    • apply(songs_data[, sapply(songs_data, is.numeric)], 2, fivenum):

      • 各数値列の5数要約(最小値、第1四分位数、中央値、第3四分位数、最大値)を計算します。
  5. 平均値、標準偏差、5数要約をデータフレームにまとめる:

    • data.frame関数で、平均値、標準偏差、および5数要約をまとめたデータフレームを作成します。
  6. 結果を表示:

    • mutate(across(where(is.numeric), ~ round(., 3)))を使って、数値列を小数点第3位まで丸めて表示します。
  7. 変数名の英訳:

    • colnames(songs_data) <- c(...):

      • 変数名を英語に変換します。
  8. データの整形:

    • melt(songs_data, id.vars = "Title"):

      • データを長い形式に変形します。

      • id.vars = "Title"は、曲名をIDとして指定します。

  9. 箱ひげ図の作成:

    • ggplot(melted_data, aes(x = variable, y = value)):

      • ggplot2を使って箱ひげ図を作成します。

      • aesは美学的マッピングを定義します。

    • geom_boxplot(fill = "skyblue", color = "black"):

      • 箱ひげ図を描画します。

      • fillは箱ひげ図の塗りつぶし色、colorは枠線の色を指定します。

    • theme_minimal():

      • ミニマルなテーマを適用します。
    • labs(title = "Boxplot of Variables", x = "Variable", y = "Value"):

      • グラフのタイトルと軸ラベルを設定します。
    • theme(axis.text.x = element_text(angle = 45, hjust = 1)):

      • X軸のテキストを45度回転させます。
    • facet_wrap(~ variable, scales = "free", ncol = 3):

      • 変数ごとに別々の箱ひげ図を作成し、3列に並べます。
  10. 数値データのみ抽出:

    • select(where(is.numeric))を使って、数値データのみを抽出します。
  11. 散布図行列の描画:

    • pairs.panels関数を使って、数値データの散布図行列を描画します。

      • method = "pearson": ピアソンの相関係数を使用します。

      • hist.col = "skyblue": ヒストグラムの色を指定します。

      • density = TRUE: 密度プロットを追加します。

      • ellipses = TRUE: 信頼楕円を追加します。

  12. 相関行列の計算:

    • cor(numeric_data, use = "complete.obs"):

      • 完全観測値を使って相関行列を計算します。
  13. 相関行列を長い形式に変換:

    • as.data.frame(as.table(cor_matrix)):

      • 相関行列をデータフレームに変換します。
  14. 対角要素を除外:

    • filter(Var1 != Var2):

      • 対角要素(自己相関)を除外します。
  15. 相関係数の絶対値が大きい順にソート:

    • `mutate(abs_value = abs(Freq))

1.2 散布図行列から読み取れること

selected_pairsのデータを見ると、相関行列から相関係数の絶対値が大きい3つの変数ペアが選ばれていることが分かります。ただし、同じペアが重複して含まれています。これに基づいていくつかのことが言えます:

  1. KeyとEnergyの間の負の相関:

    • KeyEnergyの間には強い負の相関(相関係数 = -0.787)が存在します。これは、曲のKeyが増加すると、Energyが減少する傾向があることを示唆しています。
  2. LivenessとAcousticnessの間の正の相関:

    • LivenessAcousticnessの間には強い正の相関(相関係数 = 0.771)が存在します。これは、曲が生演奏であることの度合い(Liveness)が高いほど、アコースティック度(Acousticness)が高い傾向があることを示唆しています。
  3. TempoとLivenessの間の正の相関:

    • TempoLivenessの間には強い正の相関(相関係数 = 0.716)が存在します。これは、曲のテンポ(Tempo)が速いほど、曲が生演奏であることの度合い(Liveness)が高い傾向があることを示唆しています。

2 Pythonだとこう書く

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import pearsonr
from pandas.plotting import scatter_matrix

# データの読み込み
songs_data = pd.read_csv("songs_data.csv")

# 平均値と標準偏差の計算
mean_values = songs_data.select_dtypes(include=[np.number]).mean()
std_values = songs_data.select_dtypes(include=[np.number]).std()

# 5数要約の計算
fivenum_values = songs_data.select_dtypes(include=[np.number]).apply(lambda x: np.percentile(x, [0, 25, 50, 75, 100])).T
fivenum_values.columns = ['Min', 'Q1', 'Median', 'Q3', 'Max']

# 平均値、標準偏差、5数要約をデータフレームにまとめる
summary_df = pd.concat([mean_values, std_values, fivenum_values], axis=1)
summary_df.columns = ['Mean', 'SD', 'Min', 'Q1', 'Median', 'Q3', 'Max']

# 結果を表示
summary_df = summary_df.round(3)
print(summary_df)

# 変数名の英訳
songs_data.columns = ["Title", "Danceability", "Energy", "Key", "Loudness", "Mode", 
                      "Speechiness", "Acousticness", "Instrumentalness", "Liveness", 
                      "Valence", "Tempo", "TimeSignature"]

# データの整形
melted_data = pd.melt(songs_data, id_vars=["Title"])

# 箱ひげ図の作成
plt.figure(figsize=(14, 8))
sns.boxplot(x='variable', y='value', data=melted_data, palette='skyblue')
plt.xticks(rotation=45)
plt.title('Boxplot of Variables')
plt.xlabel('Variable')
plt.ylabel('Value')
plt.show()

# 数値データのみ抽出
numeric_data = songs_data.select_dtypes(include=[np.number])

# 散布図行列の描画
sns.pairplot(numeric_data)
plt.show()

# 相関行列を計算
cor_matrix = numeric_data.corr()

# 相関行列を長い形式に変換
cor_long = cor_matrix.stack().reset_index()
cor_long.columns = ['Var1', 'Var2', 'Correlation']

# 対角要素を除外
cor_long = cor_long[cor_long['Var1'] != cor_long['Var2']]

# 相関係数の絶対値が大きい順にソート
cor_long['abs_value'] = cor_long['Correlation'].abs()
cor_long = cor_long.sort_values(by='abs_value', ascending=False)

# 重複のないように変数ペアを選択
selected_pairs = cor_long.drop_duplicates(subset=['Var1', 'Var2']).head(6)

# 選択された変数を抽出
selected_vars = pd.unique(selected_pairs[['Var1', 'Var2']].values.ravel('K'))
selected_data = numeric_data[selected_vars]

# 散布図行列の再描画
sns.pairplot(selected_data)
plt.show()

2.1 コードの説明

  1. パッケージの読み込み:

    • pandas: データ操作と分析に使用します。

    • numpy: 数値計算に使用します。

    • seaborn: データの視覚化に使用します。

    • matplotlib: グラフ作成に使用します。

    • scipy.stats: 統計関数に使用します。

  2. データの読み込み:

    • pd.read_csv("songs_data.csv")を使ってCSVファイルからデータを読み込みます。
  3. 平均値と標準偏差の計算:

    • mean_values = songs_data.select_dtypes(include=[np.number]).mean(): 数値列の平均値を計算します。

    • std_values = songs_data.select_dtypes(include=[np.number]).std(): 数値列の標準偏差を計算します。

  4. 5数要約の計算:

    • fivenum_values = songs_data.select_dtypes(include=[np.number]).apply(lambda x: np.percentile(x, [0, 25, 50, 75, 100])).T: 各数値列の5数要約を計算します。

    • fivenum_values.columns = ['Min', 'Q1', 'Median', 'Q3', 'Max']: 列名を設定します。

  5. 平均値、標準偏差、5数要約をデータフレームにまとめる:

    • summary_df = pd.concat([mean_values, std_values, fivenum_values], axis=1): 平均値、標準偏差、5数要約を1つのデータフレームにまとめます。

    • summary_df.columns = ['Mean', 'SD', 'Min', 'Q1', 'Median', 'Q3', 'Max']: 列名を設定します。

  6. 結果を表示:

    • summary_df = summary_df.round(3): 小数点第3位まで丸めます。

    • print(summary_df): 結果を表示します。

  7. 変数名の英訳:

    • songs_data.columns = ["Title", "Danceability", "Energy", "Key", "Loudness", "Mode", "Speechiness", "Acousticness", "Instrumentalness", "Liveness", "Valence", "Tempo", "TimeSignature"]: 変数名を英語に変更します。
  8. データの整形:

    • melted_data = pd.melt(songs_data, id_vars=["Title"]): データを長い形式に変形します。
  9. 箱ひげ図の作成:

    • sns.boxplot(x='variable', y='value', data=melted_data, palette='skyblue'): 箱ひげ図を作成します。

    • plt.xticks(rotation=45): X軸ラベルを45度回転させます。

    • plt.title('Boxplot of Variables'): グラフのタイトルを設定します。

    • plt.xlabel('Variable'): X軸ラベルを設定します。

    • plt.ylabel('Value'): Y軸ラベルを設定します。

    • plt.show(): グラフを表示します。

  10. 数値データのみ抽出:

    • numeric_data = songs_data.select_dtypes(include=[np.number]): 数値データのみを抽出します。
  11. 散布図行列の描画:

    • sns.pairplot(numeric_data): 数値データの散布図行列を描画します。

    • plt.show(): グラフを表示します。

  12. 相関行列の計算:

    • cor_matrix = numeric_data.corr(): 相関行列を計算します。
  13. 相関行列を長い形式に変換:

    • cor_long = cor_matrix.stack().reset_index(): 相関行列を長い形式に変換します。

    • cor_long.columns = ['Var1', 'Var2', 'Correlation']: 列名を設定します。

  14. 対角要素を除外:

    • cor_long = cor_long[cor_long['Var1'] != cor_long['Var2']]: 対角要素を除外します。
  15. 相関係数の絶対値が大きい順にソート:

    • cor_long['abs_value'] = cor_long['Correlation'].abs(): 相関係数の絶対値を計算します。

    • cor_long = cor_long.sort_values(by='abs_value', ascending=False): 絶対値が大きい順にソートします。

  16. 重複のないように変数ペアを選択:

    • selected_pairs = cor_long.drop_duplicates(subset=['Var1', 'Var2']).head(6): 重複を排除し、上位6つのペアを選択します。
  17. 選択された変数を抽出:

    • selected_vars = pd.unique(selected_pairs[['Var1', 'Var2']].values.ravel('K')): 選択された変数を抽出します。

    • selected_data = numeric_data[selected_vars]: 選択された変数を含むデータを取得します。

  18. 散布図行列の再描画:

    • sns.pairplot(selected_data): 選択された変数の散布図行列を描画します。

    • plt.show(): グラフを表示します。