21EC001 青木杜馬
近年、音楽市場は定額ストリーミングサービス(以下、サブスク)の普及により急速に変化している。世界の音楽市場では、CDやレコードなどのフィジカル媒体が減少し、デジタル配信やストリーミングサービスが主要な収益源となっている。世界の音楽業界の収益推移を図1.1に示す。
一方で、日本の音楽市場においてもサブスクの利用は拡大しているが、依然としてCD売上が収益の大部分を占めている。これは、音楽市場規模で世界1位のアメリカが収益の約8割をサブスクで得ている状況と対照的である。Spotify Chartsのウィークリーチャートの各週の総再生回数の推移を図1.2、2023年の日本の音楽収益割合を図1.3、アメリカの音楽収益割合を図1.4に示す。
このように、日本は世界第2位の音楽市場を持ちながら、収益構造においてアメリカとは顕著な違いが見られる。
本研究では「日本とアメリカの音楽市場におけるヒット曲の特性」を比較・分析することで、両国の市場構造や音楽消費の特徴を明らかにすることを目的とする。
分析には、Spotifyが提供する「Spotify Charts」のデータを用い、2017年8月から2024年8月までの約7年分のウィークリーチャートを対象とする。
図1.1 世界の音楽業界の収益推移 1999-2023(US$billions)
出典:IFPI | GLOBAL MUSIC REPORT 2024
図1.2 ウィークリーチャートの合計再生回数推移
図1.3 日本の音楽収益割合(2023)
出典:RIAJ | The Recoding Industry in Japan 2024
図1.4 アメリカの音楽収益割合(2023)
出典:RIAA | 2023 Year-End Music Industry Revenue Report
Spotifyとは、数千万もの音楽やポッドキャスト、ビデオを楽しめる世界最大手の音楽配信サービスである。音楽再生などの基本機能は無料であるが、Spotify Premiumにアップグレードすることもできる。
図2.1 Spotify ホーム画面
Spotify Chartsとは、Spotifyが提供している再生回数を元にしたランキングである。73か国と地域、さらにそれらを合算したグローバルチャートが含まれている。デイリーチャートは通常、チャート期間の翌日に東部標準時(EST)午後6時(協定世界時(UTC)午後10時)より前に公開され、ウィークリーチャートは、すべてのタイムゾーンがウィークリーチャートの期間を迎えた後に発表される。ウィークリーチャートの期間は金曜日に始まり、次の木曜日に終わる。
Spotify Chartsでは、ウィークリーチャートやデイリーチャートなどの複数の種類のチャートが存在し、これらのチャートは、Spotifyのアカウントを有していれば、Spotify Charts(https://charts.spotify.com)にて無料で閲覧できる。また、Weekly Top Songs, Daily Top Songs, Daily Viral Songsはcsv形式で取得することができる。
図2.2 Spotify Charts ホーム画面
ジップの法則とは、アメリカの言語学者のジョージ・キングズリー・ジフが発見した経験則であり、サイズや頻度の大きさで順位kを付けた場合、k番目のサイズは、1番目のサイズの1/kに比例するとされるものである。この法則は、自然言語処理の分野では単語の出現頻度の分布として知られており、最も頻出する単語の出現回数が2番目の単語の約2倍、3番目の単語の約3倍になることが観測される。
本研究では、Spotify Chartsの順位ごとの平均再生回数がジップの法則に従うかを検証した。
確率密度関数とは、確率、または確率密度を計算する関数である。連続確率変数Xについて、ある関数y=f(x)が下式を満たすとき、f(x)はXについての確率密度関数となる。 \[ f(x) \geq 0, \quad \int_{-\infty}^{\infty} f(x)\, dx = 1 \]
このとき、確率変数Xについて、以下のように表現できる。 \[ P(a \leq x \leq b) = \int_{a}^{b} f(x) \,dx \]
例えば、金融データではリターンの分布、医学では患者の体温の分布、機械学習では特徴量の分布が解析対象となる。
本研究では、順位ごとの次週順位の分布を解析する際に、この確率密度関数を推定するための手法としてカーネル密度推定を採用した。
カーネル密度推定(Kernel Density Estimation, KDE)とは、確率密度関数を推定するための非パラメトリック手法である。カーネル密度推定では、以下のようにして確率密度関数f(x)を推定する。\[ f(x) = \frac{1}{n h} \sum_{i=1}^{n} K\left(\frac{x - x_i}{h}\right) \]
ここで、
カーネル関数は、各データ点周辺の密度を滑らかにするための関数であり、以下のようなものが使用される。
バンド幅は推定結果に大きく影響を与え、バンド幅が小さいと分布が細かくなり、バンド幅が大きいと分布が滑らかになる。
本研究では、Spotify Chartsの順位データを基に、次週順位を非パラメトリックに推定し、楽曲の順位変動の傾向を把握した。Pythonのデータ分析ライブラリであるseabornを用いて、この推定を実行した。Pythonのseaborn.kdeplot()では、デフォルトでバンド幅を調整するアルゴリズムが適用される。
本研究では、日本およびアメリカのSpotifyウィークリーチャートデータを対象とし、2017年8月25日から同年8月30日までの集計分を起点とし、2024年8月23日から同年8月29日までの集計分に至る、約7年間にわたるデータを使用した。このデータは、Spotify公式サイト(https://charts.spotify.com)で提供されており、各週のトップ200位のランキングが記録されている。
Spotify Chartsのcsvファイルに含まれる要素を表1に示す。
| 要素 | 説明 |
|---|---|
| rank | 順位 |
| uri | 楽曲の一意識別子 |
| artist_name | アーティスト名 |
| song_name | 曲名 |
| source | レーベル名 |
| peak_rank | 最高順位 |
| previous_rank | 先週の順位 |
| weeks_on_chart | 連続チャートイン数 |
| streams | 再生回数 |
Spotify Chartsのウィークリーチャートは、Spotify公式サイト(https://charts.spotify.com)から、各国・地域ごとにcsv形式でダウンロードできる。本研究では、日本およびアメリカのチャートを選択し、各週のデータを取得した。
以下に、データ収集の具体的な手順を示す。
取得したウィークリーチャートを用いて、2018年から2023年の年間チャートイン曲数の推移を図3に示す。
図3 年間チャートイン曲数推移
図3より、日本の年間チャートイン曲数は、2018年の830曲から2023年の624曲へと徐々に減少しており、楽曲の入れ替わりが少ない傾向が見られる。
アメリカでは、年間チャート曲数が2018年から2020年にかけて増加した後、2021年以降は減少傾向にある。しかし、日本よりも多くの曲がチャートインしており、楽曲の入れ替わりが比較的活発であるといえる。
本研究では、日本とアメリカのSpotify Chartsのウィークリーチャートを用いた分析を行った。データ処理と分析にはPythonを使用し、プログラムコードは付録に記載する。
本研究で使用したデータは以下の手順でデータの収集と前処理を行った。
本分析では、Spotify Chartsのウィークリーチャートを用いて、順位ごとに次週順位と平均変動幅を算出し、可視化を行い日本とアメリカのチャートにおける楽曲の安定性と動向の違いを明らかにすることを目的とする。
以下の手順で分析を行った。
各国の順位ごとの平均変動幅を可視化したグラフを図4.1に示す。
図4.1 日米の順位ごとの平均変動幅分布
図4.1は、日本とアメリカごとの平均変動幅を同一のグラフに示したである。また、図4.2および図4.3は、それぞれ日本とアメリカのデータを独立して示し、最も適した近似式をプロットしたものである。
図4.2 日本の順位ごと平均変動幅と累乗近似
図4.3 アメリカの平均変動幅と対数近似
図4.2より、日本では順位が低くなるにつれ変動幅が大きくなる傾向が見られたが、アメリカは全体的に変動幅が大きく、特に下位の楽曲ほど変動が激しいことがわかる。表2.1に算出した近似式および決定係数を示す。
| 国 | 近似式 | 決定係数 |
|---|---|---|
| 日本 | \[ y = 5.92 e-01 \times x^{0.637} \] | 0.8985 |
| アメリカ | \[ y = 3.42 \ln(x) + 1.58 \] | 0.8236 |
本分析では、Spotify Chartsのウィークリーチャートを用いて、順位ごとの再生回数の平均を算出し、日本とアメリカのチャートの特性を比較した。再生回数は順位が低くなるにつれて減少する傾向があるが、その減少の度合いが国ごとに違いが生じるのかを明らかにすることを目的とする。
以下の手順で分析を行った。
図4.4および図4.5は、それぞれ日本とアメリカの順位ごとの平均再生回数を示したものである。図4.6および図4.7は、同データを両対数グラフに変換し、近似式をプロットしたものである。
図4.4 日本の順位ごと平均再生回数
図4.5 アメリカの順位ごと平均再生回数
図4.6 日本の順位ごとの平均再生回数と近似式(両対数)
図4.7 アメリカの順位ごとの平均再生回数と近似式(両対数)
表2.2に算出した近似式と決定係数を示す。
| 国 | 近似式 | 決定係数 |
|---|---|---|
| 日本 | \[ y = 2.08 e \times 06 x^{-0.435} \] | 0.9114 |
| アメリカ | \[ y = 1.61 e \times 07 x^{-0.411} \] | 0.9864 |
これらの結果より、日本とアメリカの特徴として、再生回数の分布や楽曲の人気の集中度に差異があることがわかった。日本では指数が-0.435であり、再生回数が上位の楽曲に集中しているのに対し、アメリカでは指数は-0.411と低く、より多くの楽曲が均等に再生されていることがわかった。また、ジップの法則が適用可能な順位範囲においても、日本は61位に対しアメリカは200位までが適合する結果になった。
本分析は、Spotify Chartsのウィークリーチャートを用いて、カーネル密度推定を活用して、順位ごとの次週順位の確率密度関数を算出した。さらに、この分布を基に、日本とアメリカのチャート特性の違いを比較した。
以下の手順で分析を行った。
各順位の確率密度関数を重ねた日本のグラフを図4.8、アメリカのグラフを図4.9に示す。また、標準化を行い重ねた日本のグラフを図4.10、アメリカのグラフを図4.11に示す。
図4.8 順位ごとの確率密度関数
図4.9 順位ごとの確率密度関数
図4.10 標準化を行った確率密度関数 日本
図4.11 標準化を行った確率密度関数 アメリカ
図4.10および図4.11より、標準化された分布には大きく2つの山が見られた。これにより分布には2つの特徴的なパターンが存在することがわかった。この観察結果を基に、次週順位分布を2つのグループに分類する試みを行った。図4.12と図4.13に日本の分布を上位175曲と下位25曲で分類したグラフを示す。図4.14と図4.15にアメリカの分布を上位165曲と下位35曲で分類したグラフを示す。
図4.12 上位175曲の確率密度関数 日本
図4.13 下位25曲の確率密度関数 日本
図4.14 上位165曲の確率密度関数 アメリカ
図4.15 下位25曲の確率密度関数 アメリカ
図4.12より、日本の1位から175位までの楽曲の確率密度関数のピークはわずかに左側に位置しており、これらの楽曲は次週に順位を上げる傾向があることがわかった。
図4.13より、日本の176位から200位までの楽曲の確率密度関数のピークはわずかに右側に位置しており、これらの楽曲は次週に順位を下げる傾向があることがわかった。
図4.14より、アメリカの1位から165位までの楽曲の確率密度関数のピークは日本と同様にわずかに左側に位置しており、これらの楽曲は次週順位を上げる傾向があることがわかった。
図4.15より、アメリカの166位から200位までの楽曲の確率密度関数はピークも日本と同様にわずかに右側に位置しており、これらの楽曲は次週に順位を下げる傾向があることがわかった。
日本とアメリカのウィークリーチャートにおける順位ごとの平均変動幅を算出し、可視化を行った。日本では、上位から下位にかけて緩やかに変動幅が増加する傾向がみられた。
一方で、アメリカでは、日本に比べて全体的に変動幅が大きいことがわかった。また、チャートの観察を通じて、アメリカのチャートではテイラー・スウィフトなどの有名アーティストがアルバムをリリースすると、アルバム収録曲が一斉にチャート上位を占めることある点が印象的だった。この現象は、アルバムリリースがチャートの動きに与える影響を示している可能性がある。日本のチャートでは、こうしたアルバム単位の一斉ランクインはあまり見られないことから、両国の音楽市場の特性の違いが反映されているのではないかと考えられる。
日本とアメリカそれぞれの順位ごとの平均再生回数を算出し、両対数グラフに変換し可視化を行った結果、日本とアメリカともに順位が低くなるにつれて再生回数が減少し、Zipfの法則に従う傾向が見られた。図4.4および図4.6を詳細に観察すると、日本では上位50位付近で再生回数に明確な差が見られ、50位以内の楽曲はそれ以下の楽曲と比べて再生回数が顕著に高い傾向があることがわかる。この結果は、日本のランキングにおいて「上位楽曲の独占的な人気」が存在していることを示していることがわかる。
これに対し、アメリカでは順位に応じた再生回数の減少が比較的滑らかであり、特定の順位で再生回数が大きく変化するような顕著な差は見られない。この点から、アメリカのランキングでは幅広い楽曲が聴かれる傾向が示唆される。すなわち、日本の市場では上位50位以内に「ヒット曲」が集中する一方で、アメリカでは再生回数がより多様な楽曲に分散していると考えられる。
日本とアメリカの各順位の次週順位の分布にカーネル密度推定を用いて分析を行った。日本とアメリカともに標準化した分布において大きく分けて2パターンの傾向があることがわかった。日本のランキングは特定の順位に曲が固定されやすく、安定性が高いことが分かります。アメリカでは順位変動の幅が大きく、市場の流動性が高いといえます。この結果は、日米の音楽市場における流行の持続性や消費者の嗜好の違いを反映している可能性がある。
本研究では、Spotifyのウィークリーチャートのデータを基に、日本とアメリカの音楽市場におけるランキング動向を比較と分析を行った。順位ごとの平均変動幅、平均再生回数、次週順位確率密度関数という3つの観点から、それぞれの市場の特性を明らかにした。
本研究で使用したプログラムコードを載せ、説明を行う。
Spotifyのチャートデータを、使用しやすいようにデータの整形を行った。本処理では、以下のコードを使用して、指定された列順に並び替え新たに保存した。
import pandas as pd
import os
# CSVファイルが入ったフォルダーのパスを指定
folder_path = "./"
# すべてのCSVファイルを取得
csv_files = [f for f in os.listdir(folder_path) if f.endswith('.csv')]
# 出力フォルダーのパスを指定
output_folder_path = os.path.join(folder_path, "ordered")
# 出力フォルダーが存在しない場合は作成
os.makedirs(output_folder_path, exist_ok=True)
# 列の並び順を指定
desired_order = ['uri', 'rank', 'artist_names', 'track_name', 'streams', 'weeks_on_chart', 'source', 'peak_rank', 'previous_rank']
# 各CSVファイルを読み込み、列を並び替え
for file in csv_files:
file_path = os.path.join(folder_path, file)
try:
# CSVファイルを読み込み(エンコーディングを指定)
df = pd.read_csv(file_path, encoding='utf-8')
# 1行目の値を読み込み、列の順序を指定された順序に並び替え
ordered_df = df[desired_order]
# 並び替えたデータフレームを新しいファイル名で保存
ordered_file_path = os.path.join(output_folder_path, f"ordered_{file}")
ordered_df.to_csv(ordered_file_path, index=False, encoding='utf-8-sig')
print(f"Columns in {file} reordered and saved to {ordered_file_path}")
except Exception as e:
print(f"Failed to process {file_path}: {e}")
print("Processing complete.")
以下は、フォルダー内のウィークリーチャートcsvファイルを読込み、曲ごとに統合したフレームを作成するコードである。このコードは、各曲の順位と再生回数を週ごとに統合した形で出力する。
def FtoF(folder_path):
import os
import pandas as pd
files = os.listdir(folder_path) # フォルダ内のファイルリスト
result = [] # 結果を格納するリスト
for file_index, file in enumerate(files):
try:
file_path = os.path.join(folder_path, file)
df = pd.read_csv(file_path)
# A列からF列を抽出
data_columns = df.iloc[:, :6].values
for row in data_columns:
uri = row[0]
rank = row[1]
artist_name = row[2]
song_name = row[3]
play_count = row[4]
found = False
for res in result:
if res[1] == artist_name and res[2] == song_name:
position = 3 + file_index * 2
while len(res) <= position + 1:
res.append('')
res[position] = rank
res[position + 1] = play_count
res[0] = uri # URIを更新
found = True
break
# 新しいエントリを追加
if not found:
new_entry = [uri, artist_name, song_name] + [''] * (file_index * 2)
new_entry.extend([rank, play_count])
result.append(new_entry)
except Exception as e:
print(f"Failed to open or process {file}: {e}")
if result:
max_columns = max(len(res) for res in result) # 最大列数を計算
# 列名を生成
columns = ['uri', 'artist_names', 'track_name'] + \
[f'rank{i // 2 + 1}' if i % 2 == 0 else f'streams{i // 2 + 1}' for i in range(max_columns - 3)]
# 各行の列数を最大列数に揃える
for res in result:
while len(res) < max_columns:
res.append('')
# DataFrameに変換
result_df = pd.DataFrame(result, columns=columns)
result_df.columns = result_df.columns.str.lower()
return result_df
print("結果が空です。")
return pd.DataFrame() # 空のDataFrameを返す
このコードは、各週のチャート順位データをもとに、ある順位が次週にどの順位になるのかを集計するためのコードである。
def TNR(rank_df):
import pandas as pd
# 200位までの順位を考慮
max_rank = 200
# 結果を格納するデータフレームを作成
result_df = pd.DataFrame(
index=range(1, max_rank + 1),
columns=[f"next_week{i+1}" for i in range(len(rank_df.columns) - 1)]
)
result_df.index.name = "rank"
# 次週の順位を集計
for week in range(len(rank_df.columns) - 1):
current_week = rank_df.columns[week]
next_week = rank_df.columns[week + 1]
# 現在の週の順位と次週の順位を取得
for rank in range(1, max_rank + 1):
# 現在の週で該当順位の次週の順位を抽出
next_rank_values = rank_df[next_week][rank_df[current_week] == rank]
# 次週の順位が存在しない場合は201を代入
if not next_rank_values.empty:
result_df.loc[rank, f"next_week{week+1}"] = next_rank_values.iloc[0]
else:
result_df.loc[rank, f"next_week{week+1}"] = 201 # 空白を201で補完
# 結果を数値型に変換
result_df = result_df.apply(pd.to_numeric, errors=('coerce')).fillna(201)
return result_df
このコードは、順位ごとの平均変動幅の算出と可視化に使用した。
import matplotlib.pyplot as plt
import pandas as pd
def plot_fluctuation(abs_rank_JP, abs_rank_US):
"""
日本とアメリカの順位ごとの平均変動幅を可視化する
:param abs_rank_JP: 日本の平均変動幅データフレーム
:param abs_rank_US: アメリカの平均変動幅データフレーム
"""
plt.figure(figsize=(12, 6))
# 日本のデータをプロット
plt.plot(abs_rank_JP['rank'], abs_rank_JP['RCA'], label='日本', marker='o', linestyle='-', alpha=0.7)
# アメリカのデータをプロット
plt.plot(abs_rank_US['rank'], abs_rank_US['RCA'], label='アメリカ', marker='x', linestyle='--', alpha=0.7)
# グラフの設定
plt.title('順位ごとの平均変動幅', fontsize=14)
plt.xlabel('順位', fontsize=12)
plt.ylabel('平均変動幅', fontsize=12)
plt.legend(fontsize=12)
plt.grid(True, linestyle='--', alpha=0.6)
plt.tight_layout()
# グラフの表示
plt.show()
# プログラム全体の統合
if __name__ == "__main__":
# 必要なデータを読み込み、計算
rank_columns = [col for col in rank_JP.columns if col.startswith('rank')]
rank_JP = rank_JP.apply(pd.to_numeric, errors='coerce')
abs_rank_JP = CRF(rank_JP, rank_columns)
abs_rank_JP = abs_rank_JP.mean(axis=1)
abs_rank_JP = pd.DataFrame({
'rank': abs_rank_JP.index+1,
'RCA': abs_rank_JP.values
})
rank_US = rank_US.apply(pd.to_numeric, errors='coerce')
abs_rank_US = CRF(rank_US, rank_columns)
abs_rank_US = abs_rank_US.mean(axis=1)
abs_rank_US = pd.DataFrame({
'rank': abs_rank_US.index+1,
'RCA': abs_rank_US.values
})
# 描画機能の呼び出し
plot_fluctuation(abs_rank_JP, abs_rank_US)
このコードは、平均変動幅を累乗関数および対数関数で近似し、それぞれの近似式および決定係数を算出します。また、近似曲線をデータをもとに可視化します。
# 必要なライブラリのインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
plt.rcParams['font.family'] = 'Meiryo'
# データの再読み込み
JP_df = pd.read_csv("./JP/順位毎の平均変動幅_JP.csv")
US_df = pd.read_csv("./US/順位毎の平均変動幅_US.csv")
# 累乗関数と対数関数の定義
def power_law(x, a, b):
return a * np.power(x, b)
def log_function(x, a, b):
return a * np.log(x) + b
# XとYのデータ
x_JP = JP_df['rank']
y_JP = JP_df['RCA']
x_US = US_df['rank']
y_US = US_df['RCA']
# 日本:累乗近似
popt_JP, _ = curve_fit(power_law, x_JP, y_JP)
y_fit_JP = power_law(x_JP, *popt_JP)
r2_JP = 1 - np.sum((y_JP - y_fit_JP)**2) / np.sum((y_JP - np.mean(y_JP))**2)
# アメリカ:対数近似
popt_US, _ = curve_fit(log_function, x_US, y_US)
y_fit_US = log_function(x_US, *popt_US)
r2_US = 1 - np.sum((y_US - y_fit_US)**2) / np.sum((y_US - np.mean(y_US))**2)
# 近似式と決定係数の出力
jp_eq = f"日本の累乗近似式: y = {popt_JP[0]:.2e} * x^{popt_JP[1]:.3f}, R^2 = {r2_JP:.4f}"
us_eq = f"アメリカの対数近似式: y = {popt_US[0]:.2f}ln(x) + {popt_US[1]:.2f}, R^2 = {r2_US:.4f}"
print(jp_eq)
print(us_eq)
# グラフ描画
plt.figure(figsize=(10, 6))
plt.scatter(x_US, y_US, label="アメリカ (実データ)")
plt.plot(x_US, y_fit_US, color="red", label=f"対数近似 (アメリカ)")
plt.xlabel("順位")
plt.ylabel("平均変動幅")
plt.legend()
plt.grid(True)
plt.title("アメリカ 順位毎の平均変動幅(対数近似)")
plt.show()
本関数ExtPCは、楽曲の再生回数情報を含むデータフレーム(file_df)から、再生回数のみを抽出して新しいデータフレームとして返すものである。
def ExtPC(file_df):
#列番号を指定
count_columns = list(range(4, len(file_df.columns), 2))
#上記の列番号を抽出
count_df = file_df.iloc[:, count_columns]
count_df.columns = [f"streams{i+1}" for i in range(len(count_columns))]
#返却
return count_df
本関数PCA_rankは、ウィークリーチャートデータから順位ごとの平均再生回数を計算し、可視化するものである。
def PCA_rank(PCR_df, country_name):
import matplotlib.pyplot as plt
# 各順位の平均再生回数を計算
PCR_ave = PCR_df.mean(axis='columns') # 行方向に平均を計算
# 可視化
plt.figure(figsize=(12, 6))
plt.plot(PCR_ave, marker='o', label=f"{country_name} 平均再生回数")
plt.xlabel("順位", fontsize=12)
plt.ylabel("平均再生回数", fontsize=12)
plt.legend(loc='upper right', fontsize=10)
plt.grid(True, which="both", linestyle='--', alpha=0.7)
plt.title(f"順位毎の平均再生回数 ({country_name})", fontsize=14)
plt.tight_layout()
plt.show()
このコードは、両対数グラフに変換し、近似曲線を追加するコード。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from sklearn.metrics import r2_score
plt.rcParams['font.family']='Meiryo'
# データの読み込み
PCA_JP = pd.read_csv("./JP/順位毎の平均再生回数_JP.csv")
PCA_US = pd.read_csv("./US/順位毎の平均再生回数_US.csv")
# 累乗近似関数
def power_law(x, a, b):
return a * np.power(x, b)
# 近似とプロット関数
def plot_and_fit_power_law(df, country_name):
x = df['rank']
y = df['PC_avg']
# 累乗近似
popt, pcov = curve_fit(power_law, x, y)
a, b = popt
# 近似データ
y_fit = power_law(x, *popt)
# 決定係数 (R^2)
r2 = r2_score(y, y_fit)
# プロット
plt.figure(figsize=(10, 6))
plt.scatter(x, y, label="実データ", alpha=0.7)
plt.plot(x, y_fit, color='red', label=f"累乗近似: y={a:.2e}x^{b:.3f}\nR²={r2:.4f}")
plt.title(f"{country_name} 順位毎の平均再生回数(累乗近似)", fontsize=14)
plt.xlabel("順位", fontsize=12)
plt.ylabel("平均再生回数", fontsize=12)
plt.yscale('log')
plt.xscale('log')
plt.legend()
plt.grid(True)
plt.show()
print(f"{country_name} 近似式: y = {a:.2e} * x^{b:.3f}")
print(f"{country_name} 決定係数 (R²): {r2:.4f}")
# 日本のデータでプロットと近似
plot_and_fit_power_law(PCA_JP, "日本")
# アメリカのデータでプロットと近似
plot_and_fit_power_law(PCA_US, "アメリカ")
このコードは、次週順位データをもとにカーネル密度推定を行おうコード。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.family']='Meiryo'
# 次週順位データの読み込み
next_rank_JP = pd.read_csv("./.csv", index_col=0)
plt.figure(figsize=(12, 8))
for rank in next_rank_JP.index:
rank_data = next_rank_JP.loc[rank].dropna()
# KDEプロット (標準化なし)
sns.kdeplot(rank_data, label=f"{rank}位", alpha=0.4)
plt.title("日本 次週順位の確率密度関数", fontsize=14)
plt.xlabel("次週順位", fontsize=12)
plt.ylabel("密度", fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xlim(1, 201) # 順位の範囲
plt.yticks([0.0, 0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14, 0.16])
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
このコードは、A.4.1で作成したものを重ねて表示するコード。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import norm
plt.rcParams['font.family']='Meiryo'
# データの読み込み
next_rank_JP = pd.read_csv("./JP/次週順位_JP.csv", index_col=0)
# 標準化して重ねる
plt.figure(figsize=(12, 8))
for rank in next_rank_JP.index:
rank_data = next_rank_JP.loc[rank].dropna()
# 標準化 (Zスコア)
standardized_data = (rank_data - rank_data.mean()) / rank_data.std()
sns.kdeplot(standardized_data, alpha=0.4, label=f"{rank}位", linewidth=1)
# グラフの設定
plt.title("日本 確率密度関数", fontsize=14)
plt.xlabel("標準化された次週順位", fontsize=12)
plt.ylabel("密度", fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xlim(-5, 5)
plt.legend(title="現在の順位", bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()
このコードは上位と下位に分類わけする際に使用した。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import norm
plt.rcParams['font.family']='Meiryo'
# データの読み込み
next_rank_US = pd.read_csv("./US/次週順位_US.csv", index_col=0)
# 上位・下位でグラフを分ける
plt.figure(figsize=(12, 8))
# 上位100位 (1~100位)
for rank in next_rank_US.index:
if rank <= 165: # 上位100位をフィルタリング
rank_data = next_rank_US.loc[rank].dropna()
standardized_data = (rank_data - rank_data.mean()) / rank_data.std()
sns.kdeplot(standardized_data, alpha=0.5, label=f"{rank}位", linewidth=1)
plt.title("アメリカ 確率密度関数 (1位~165位)", fontsize=14)
plt.xlabel("標準化された次週順位", fontsize=12)
plt.ylabel("密度", fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xlim(-5, 5)
plt.legend(title="現在の順位", bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()
# 下位100位 (101~200位)
plt.figure(figsize=(12, 8))
for rank in next_rank_US.index:
if rank > 165: # 下位101~200位をフィルタリング
rank_data = next_rank_US.loc[rank].dropna()
standardized_data = (rank_data - rank_data.mean()) / rank_data.std()
sns.kdeplot(standardized_data, alpha=0.5, label=f"{rank}位", linewidth=1)
plt.title("アメリカ 確率密度関数 (166位~200位)", fontsize=14)
plt.xlabel("標準化された次週順位", fontsize=12)
plt.ylabel("密度", fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xlim(-5, 5)
plt.legend(title="現在の順位", bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()