【Matplotlib】Pythonで作るデータ可視化

[前回の記事](https://qiita.com/wooooo/items/fa2bccf09da9601469d7)では、バレーボール🏐SVリーグ男子の優勝決定戦（サントリーサンバーズ大阪 vs ジェイテクトSTINGS愛知）のデータ分析を行いました。

今回は、その分析コードを実行することで生成される様々な可視化グラフについて詳しく解説します。

# はじめに
データ分析では、数値だけでなくビジュアライゼーションが重要です。特にスポーツデータの分析では、チームや選手の特徴を視覚的に表現することで、より深い洞察が得られます。

今回は、GitHubで公開している[SVリーグ分析プロジェクト](https://github.com/ssssswooooo/svleague_analysis)のコードを実行すると生成される5つの主要なグラフについて解説します。


# 必要なライブラリ
まず、可視化に使用している主なライブラリを確認しましょう
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib  # 日本語表示用
```
特に`japanize_matplotlib`は、matplotlibで日本語を正しく表示するために必要なライブラリです。


## 1. チーム別得点構成グラフ
#### コード解説
```python:scripts/analyze_finals.py
# チーム別の得点データを集計
teams = [team1, team2]
attack = [suntory_attack, jtekt_attack]
block = [suntory_block, jtekt_block]
serve = [suntory_serve, jtekt_serve]

# 積み上げ棒グラフを作成
bar_width = 0.5
x = np.arange(len(teams))

# プロット
ax.bar(x, attack, bar_width, label='アタック', color='#3498DB')
ax.bar(x, block, bar_width, bottom=attack, label='ブロック', color='#E74C3C')
ax.bar(x, serve, bar_width, bottom=[a+b for a, b in zip(attack, block)], 
       label='サーブ', color='#F1C40F')
```

#### 生成されるグラフ
![team_composition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/28c32e71-4e5b-44c8-9e04-83da2708d719.png)

このグラフは各チームの総得点をアタック、ブロック、サーブの3要素に分解して表示しています。色分けにより、各チームの得点構成の特徴が一目で分かります。

- サントリー：アタック（青）、ブロック（赤）、サーブ（黄）
- ジェイテクト：同様の色分けで表示

## 2. トップ選手比較レーダーチャート
#### コード解説

```python:scripts/analyze_finals.py
# レーダーチャートの準備
categories = ['アタック効率', 'ブロック貢献度', 'サーブ得点力', 
             'セット効率', '試合効率']

# 正規化のための最大値を計算
max_values = {
    'アタック効率': max(suntory_top['アタック'] / suntory_top['セット数'], 
                        jtekt_top['アタック'] / jtekt_top['セット数']),
    # ... 他の指標も同様に計算
}

# レーダーチャートの描画
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, polar=True)

# 両選手のデータをプロット
ax.plot(angles, suntory_values, 'b-', linewidth=2, label=f"{suntory_top['氏名']}")
ax.fill(angles, suntory_values, 'b', alpha=0.1)
ax.plot(angles, jtekt_values, 'r-', linewidth=2, label=f"{jtekt_top['氏名']}")
ax.fill(angles, jtekt_values, 'r', alpha=0.1)
```
#### 生成されるグラフ
![top_players_radar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/5553d197-fe2f-40a0-b40e-8bd8899c72ba.png)

レーダーチャートでは、両チームのエース選手（ムセルスキーとデファルコ）を5つの指標で比較しています。

1. アタック効率：セットあたりのアタック得点
2. ブロック貢献度：総得点に占めるブロックの割合
3. サーブ得点力：セットあたりのサーブ得点
4. セット効率：セットあたりの総得点
5. 試合効率：試合あたりの総得点

## 3. サーブ・ブロック得点比較
#### コード解説

```python:scripts/analyze_finals.py
# サーブとブロックの上位選手を抽出
suntory_top_server = suntory.sort_values('サーブ', ascending=False).iloc[0]
jtekt_top_server = jtekt.sort_values('サーブ', ascending=False).iloc[0]

# 2つのグラフを並べて表示
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

# サーブ得点の比較
ax1.bar(server_names, server_values, color=server_colors)
ax1.set_title('サーブ得点比較')

# ブロック得点の比較
ax2.bar(blocker_names, blocker_values, color=blocker_colors)
ax2.set_title('ブロック得点比較')
```

#### 生成されるグラフ
![serve_block_analysis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/234b0634-1ec2-4458-9a6d-66b8af8b2143.png)

このグラフは各チームのサーブとブロックのスペシャリストを比較しています。左側がサーブ得点、右側がブロック得点のトップ選手を示しています。

## 4. 得点分散度分析グラフ
#### コード解説

```python:scripts/analyze_finals.py
# 累積得点割合の計算
suntory_cum = np.cumsum(suntory['総得点'][:top_n]) / suntory_total * 100
jtekt_cum = np.cumsum(jtekt['総得点'][:top_n]) / jtekt_total * 100

# 折れ線グラフで表示
plt.plot(range(1, top_n+1), suntory_cum, 'b-', marker='o', label=team1)
plt.plot(range(1, top_n+1), jtekt_cum, 'r-', marker='s', label=team2)

# 50%と80%のラインを追加
plt.axhline(y=50, color='gray', linestyle='--', alpha=0.5)
plt.axhline(y=80, color='gray', linestyle='--', alpha=0.5)
```

#### 生成されるグラフ
![score_distribution.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/8c389883-4f5b-47d7-9113-f83b92c6379f.png)

このグラフは、各チームの得点がどれだけ特定の選手に集中しているかを示しています。累積曲線が急な上昇を示すほど、少数の選手に得点が集中していることを意味します。

## 5. 得点効率散布図
#### コード解説

```python:scripts/visualize_teams.py
# 散布図（試合あたり得点 vs セットあたり得点）
sns.scatterplot(
    data=efficiency_df,
    x='試合あたり得点',
    y='セットあたり得点',
    hue='チーム',
    size='総得点',
    sizes=(100, 500),
    alpha=0.7,
    palette=colors
)

# 選手名のラベル付け
for i, row in efficiency_df.iterrows():
    plt.text(
        row['試合あたり得点'] + 0.2,
        row['セットあたり得点'],
        row['選手名'],
        fontsize=9
    )
```

#### 生成されるグラフ
![scoring_efficiency.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/b3a15bf7-67bb-4f7c-b6e7-0ad96b9ac4c1.png)

この散布図は、各選手の得点効率を2つの軸で表現しています。
- X軸：試合あたり得点
- Y軸：セットあたり得点
- 点の大きさ：総得点
- 色：所属チーム

右上に位置する選手ほど、両方の効率が高いことを示しています。


# グラフのカスタマイズポイント
### 1. 配色の工夫

```python:
# チームカラーの定義
team_colors = {
    'サントリーサンバーズ大阪': '#1F77B4',  # 青系
    'ジェイテクトSTINGS愛知': '#FF7F0E'      # オレンジ系
}

# 得点要素の色
element_colors = {
    'アタック': '#3498DB',  # 明るい青
    'ブロック': '#E74C3C',  # 赤
    'サーブ': '#F1C40F'     # 黄色
}
```

### 2. 日本語フォントの設定

```python
import japanize_matplotlib

# フォントサイズの調整
plt.rcParams['font.size'] = 12
plt.rcParams['axes.titlesize'] = 16
plt.rcParams['axes.labelsize'] = 14
```

### 3. グラフの保存設定
```python
# 高解像度で保存
plt.savefig('output/graph.png', dpi=300, bbox_inches='tight')

# 背景を透明にして保存
plt.savefig('output/graph_transparent.png', transparent=True)
```

# 実践的な活用方法
## 1. レポート作成での活用
これらのグラフは、以下のような場面で活用できます。

- チーム分析レポートの作成
- 選手評価資料の作成
- 試合プレビュー記事での使用
- SNSでの情報発信

## 2. インタラクティブな可視化への発展
現在のコードをベースに、さらに発展させることができます。
```python
# Plotlyを使ったインタラクティブなグラフ
import plotly.express as px
import plotly.graph_objects as go

# インタラクティブな散布図
fig = px.scatter(efficiency_df, 
                 x='試合あたり得点', 
                 y='セットあたり得点',
                 size='総得点', 
                 color='チーム',
                 hover_name='選手名',
                 title='選手別得点効率（インタラクティブ版）')
fig.show()
```

## 3. ダッシュボード化
Streamlitを使用して、インタラクティブなダッシュボードを作成することも可能です。

```python
import streamlit as st

st.title('SVリーグ分析ダッシュボード')

# チーム選択
team = st.selectbox('チームを選択', ['サントリーサンバーズ大阪', 'ジェイテクトSTINGS愛知'])

# グラフの表示
if team:
    team_data = df[df['チーム名'] == team]
    fig = create_team_chart(team_data)
    st.pyplot(fig)
```

# まとめ
今回紹介した5つのグラフは、SVリーグの選手データから様々な角度で分析を可視化したものです。それぞれのグラフには以下のような特徴があります。

- **チーム別得点構成**：得点の内訳を視覚的に比較
- **レーダーチャート**：選手の多面的な能力を一目で把握
- **サーブ・ブロック比較**：特定スキルの専門性を評価
- **得点分散度**：チームの得点依存度を分析
- **得点効率散布図**：選手のパフォーマンスを2次元で評価

# 参考リンク
- [プロジェクトのGitHubリポジトリ](https://github.com/ssssswooooo/svleague_analysis)
- [前回の記事](https://qiita.com/wooooo/items/fa2bccf09da9601469d7)