Pythonを用いた日本プロ野球（NPB）データ解析：npb_scrapingの活用と実践

主な変更点は以下の通りです。

1. **リーグ指定の修正**  
   - `ScrapingNPBBatter` や `ScrapingNPBPitcher` でリーグを指定する際は、`"Central League"` / `"Pacific League"` ではなく、**`"JPCL"` (セ・リーグ) / **`"JPPL"` (パ・リーグ) を使う必要があります。  
   - これに伴い、応用例のコード例も修正。  
2. **数値列が文字列型として読み込まれる場合の注意**  
   - 取得した `HR` 等の列が文字列 (`object`) になっていると、Matplotlib で棒グラフを描画する際に `TypeError: no numeric data to plot` が発生することがあります。  
   - 必要に応じて `pandas.to_numeric()` などで数値型に変換する方法を解説。  

---

## Pythonを用いた日本プロ野球（NPB）データ解析：npb_scrapingの活用と実践

---

### 目次
1. はじめに  
2. インストール手順  
3. 基本的な使い方  
4. 出力データの形式  
5. データの保存・可視化  
   - **5.1 数値列が文字列として読み込まれた場合の対処**  
6. 応用例  
7. まとめと今後の展望  

---

## 1. はじめに

**npb_scraping** は、日本プロ野球（NPB）の各年度における選手の成績データをスクレイピングによって取得し、Pandasのデータフレーム（DataFrame）として提供するPythonライブラリです ([GitHub - kirikei4/npb_scraping: NPB data](https://github.com/kirikei4/npb_scraping))。  
野手（打者）成績および投手成績のデータを取得でき、たとえばシーズンごとの打撃成績（安打数や本塁打数など）や投手成績（勝利数や防御率など）を含む統計データを入手できます。  
利用者は野手用の **ScrapingNPBBatter** クラスと投手用の **ScrapingNPBPitcher** クラスを使い、取得したいリーグ（セ・パ）、年度、チームを指定してデータを取得できます。データの出典は Baseball-Reference.com（米国の野球統計サイト）のNPBページであり、取得結果は分析しやすいようにPandasのDataFrame形式に整形されています。

---

## 2. インストール手順

現時点（執筆時点）では **npb_scraping** は **PyPI** に公開されておらず、`setup.py` や `pyproject.toml` といったパッケージ管理用のファイルも存在しません。そのため、**pip install git+...** のような形では直接インストールできません。代わりに以下のような方法でコードを取得し、利用することが可能です。

### 2.1 Google Colabでの利用

1. **依存ライブラリのインストール**  
   npb_scraping の実行には以下のライブラリが必要です。Colabの場合はセルにて次のコマンドを実行してください（先頭の `!` はColabでシステムコマンドを実行する際の記法です）。
   ```bash
   !pip install pandas requests beautifulsoup4 lxml
   ```
   これらがすでにインストール済みの場合、Colab上で “Requirement already satisfied” と表示されます。

2. **リポジトリのクローン**  
   まだパッケージ化されていないため、GitHub からリポジトリを直接クローンします。
   ```python
   !git clone https://github.com/kirikei4/npb_scraping.git
   ```

3. **Pythonのパスに追加**  
   クローンしたフォルダをPythonの検索パスに登録して、Pythonコードから認識できるようにします。
   ```python
   import sys
   sys.path.append('/content/npb_scraping')  # クローン先が /content の場合
   ```

4. **モジュールをインポート**  
   以上で準備完了です。以下のようにしてモジュールをインポートし、利用できます。
   ```python
   from npb_scraping.player import ScrapingNPBBatter, ScrapingNPBPitcher
   ```

### 2.2 ローカル環境での利用

ローカルPC上で使う場合も大まかな手順は同じです。

1. `git clone https://github.com/kirikei4/npb_scraping.git` でリポジトリを取得する  
2. 依存ライブラリ（pandas, requests, beautifulsoup4, lxml等）をインストールする  
3. スクリプトが所在するディレクトリをPythonのパスに追加する、もしくは `npb_scraping` フォルダを自身のプロジェクト配下に配置し直接 `import` できるようにする  

または、**フォーク先のリポジトリ**に自分で `setup.py` や `pyproject.toml` を追加してパッケージングすれば、`pip install` を使ってインストールできるようにする方法もあります。

---

## 3. 基本的な使い方

**npb_scraping** を用いることで、特定の年度・チームに所属する選手の成績一覧を取得できます。野手の成績を取得する場合は **ScrapingNPBBatter** クラスを、投手成績の場合は **ScrapingNPBPitcher** クラスを使用します。それぞれに対し、取得年度（単年もしくは複数年のリスト）とチーム名（英語表記）を指定してスクレイピングオブジェクトを作成し、`get_table()` メソッドを呼ぶことで結果のDataFrameを得ます。  
以下に、例として **2012年の横浜ベイスターズ（Yokohama Bay Stars）** のデータを取得するコードを示します。チーム名は Baseball-Reference に登録されている英語名を指定します。

```python
from npb_scraping.player import ScrapingNPBBatter, ScrapingNPBPitcher

# 野手成績を取得する例（2012年 横浜ベイスターズ）
batter_scraper = ScrapingNPBBatter(year_list=[2012], team='Yokohama Bay Stars')
batter_df = batter_scraper.get_table()  # データを取得
print(batter_df.head())  # 取得したデータフレームの先頭部分を表示

# 投手成績を取得する例（2012年および2015年 横浜ベイスターズ）
pitcher_scraper = ScrapingNPBPitcher(year_list=[2012, 2015], team='Yokohama Bay Stars')
pitcher_df = pitcher_scraper.get_table()  # データを取得
print(pitcher_df.head())
```

上記のコードでは、まず2012年の横浜ベイスターズの打者成績を取得し、続けて2012年と2015年の横浜ベイスターズの投手成績を取得しています。`year_list` 引数には取得したい年をリストで指定し、複数年分をまとめて取得できます（この例では投手成績で2012年と2015年を同時に指定）。`team` 引数にはチーム名を指定します。`get_table()` メソッドの戻り値はPandasの **DataFrame** であり、`print()` で表示すると選手ごとの成績が表形式で確認できます。

---

## 4. 出力データの形式

`get_table()` メソッドによって得られる **DataFrame** には、選手の年度別成績が行（レコード）として格納されています。データフレームは**マルチインデックス（階層化インデックス）** となっており、各行は「チーム名」「年」「選手名」で識別されます（例ではIndexとして `team`・`year`・`Name` が設定されています）。列には選手の各種成績指標が含まれます。

- **野手データの主なカラム**  
  年齢（Age）、試合数（G）、打席数（PA）、打数（AB）、得点（R）、安打（H）、二塁打（2B）、三塁打（3B）、本塁打（HR）、打点（RBI）、盗塁（SB）、盗塁刺（CS）、四球（BB）、三振（SO）、打率（AVG）、出塁率（OBP）、長打率（SLG）、OPS（OPS）など。

- **投手データの主なカラム**  
  年齢（Age）、登板数（G）、先発数（GS）、勝利数（W）、敗戦数（L）、セーブ数（SV）、ホールド数（HLD など）、投球回（IP）、被安打（H）、失点（R）、自責点（ER）、奪三振（SO）、与四球（BB）、与死球（HBP）、防御率（ERA）など。

例えば野手データでは「2012年の筒香嘉智」のように個人シーズン成績が行として表され、基本的な統計指標が一通りそろっています。

---

## 5. データの保存・可視化

取得した成績データは、**Pandas** の機能を使って自由に加工・保存できます。たとえば、DataFrameをCSVファイルとして保存するには `DataFrame.to_csv()` メソッドを利用します。マルチインデックスをそのまま保存するとインデックスもCSVに含まれるため、必要に応じて `reset_index()` で列へ変換すると便利です。

```python
# データフレームをCSVファイルとして保存（インデックスを含めない）
batter_df.reset_index().to_csv('baystars_2012_batter_stats.csv', index=False)
```

上記では `reset_index()` によりチーム名・年・選手名のインデックスを列に戻し、それも含めてCSVに出力しています。生成されたCSVをダウンロードすれば、Excelなどで後から閲覧・加工できます。

可視化についても、PandasやMatplotlibを用いて簡単に行えます。例えば、**チーム内の本塁打数上位5選手** を棒グラフで可視化するコード例は以下です。

```python
import matplotlib.pyplot as plt

# 本塁打数上位5選手のデータ（2012年 横浜ベイスターズ打者）
top5_hr = batter_df.reset_index().sort_values('HR', ascending=False).head(5)
top5_hr.plot(x='Name', y='HR', kind='bar')  # 選手名をX軸、本塁打数をY軸の棒グラフ
plt.xlabel('選手名')
plt.ylabel('本塁打数')
plt.title('2012年 横浜DeNAベイスターズ 本塁打数 上位5選手')
plt.show()
```

### 5.1 数値列が文字列として読み込まれた場合の対処

実際には、取得した列（たとえば `'HR'` や `'R'`）が文字列 (`object`) として扱われるケースもあります。その場合、上記のように `plot()` を呼び出すと  
```
TypeError: no numeric data to plot
```
というエラーが出ることがあります。  
もし `.dtypes` で確認した際に `'HR'` が `object` になっていれば、**数値型への変換** が必要です。例:

```python
import pandas as pd

# もしHRが文字列になっている場合に数値型へ変換
top5_hr['HR'] = pd.to_numeric(top5_hr['HR'], errors='coerce')  # または astype(int)
top5_hr.plot(x='Name', y='HR', kind='bar')
plt.show()
```

これにより `HR` が数値列（int/float）として認識され、グラフ描画が可能になります。

---

## 6. 応用例

**npb_scraping** で取得したDataFrameは、Pandasを使った絞り込みや複数年のトレンド分析にも活用できます。ここでは代表的な二つの応用例を紹介します。

### (a) データのフィルタリング

**npb_scraping** では、チームを指定しない代わりに **league** 引数を指定することで、**リーグ全体** のデータを取得できます。ただし、`league='Central League'` や `league='Pacific League'` ではなく  
- **`league='JPCL'`** (セ・リーグ)  
- **`league='JPPL'`** (パ・リーグ)  
と指定する点に注意してください（ライブラリの実装上そうなっているため）。  

たとえば **2020年セ・リーグ** 全打者データからヤクルトの山田哲人選手や巨人所属選手のみを抽出する場合は、次のようになります。

```python
from npb_scraping.player import ScrapingNPBBatter

# 2020年セ・リーグ（JPCL）の全体データを取得
all_cl2020 = ScrapingNPBBatter(year_list=[2020], league='JPCL').get_table()
all_cl2020 = all_cl2020.reset_index()  # インデックスを列化

# 特定の選手の成績（例：山田哲人選手）
yamada = all_cl2020[all_cl2020['Name'] == 'Tetsuto Yamada']
print(yamada)

# 特定のチームの成績（例：読売ジャイアンツ）
giants_players = all_cl2020[all_cl2020['team'] == 'Yomiuri Giants']
print(giants_players.head())
```

Pandasのブールインデックスを用いることで、「特定選手だけ」「特定チームだけ」といった自由な絞り込みが可能です。

### (b) 複数年の成績推移の分析

`year_list` に複数の年度を指定すると、同一選手の年度別成績の比較やトレンド分析ができます。例として、**2015年から2020年** の読売ジャイアンツ打者成績を取得し、坂本勇人選手の年度別本塁打数をグラフ化するコードは以下のとおりです。

```python
from npb_scraping.player import ScrapingNPBBatter
import matplotlib.pyplot as plt

# 2015〜2020年の巨人の野手成績を取得
giants_multi = ScrapingNPBBatter(year_list=list(range(2015, 2021)), team='Yomiuri Giants').get_table()
giants_multi = giants_multi.reset_index()

# 坂本勇人選手の年度別成績を抽出
sakamoto = giants_multi[giants_multi['Name'] == 'Hayato Sakamoto']

# 本塁打数(HR)が文字列になっている場合は数値変換が必要
# sakamoto['HR'] = pd.to_numeric(sakamoto['HR'], errors='coerce')

# 本塁打数の推移を折れ線グラフで可視化
plt.plot(sakamoto['year'], sakamoto['HR'], marker='o')
plt.xlabel('年度')
plt.ylabel('本塁打数')
plt.title('坂本勇人 (2015-2020) 本塁打数の推移')
plt.show()
```

実行すると坂本選手の本塁打数が年度ごとにどのように変化したかを可視化できます。単年データだけでなく、長期的な成長や衰退の傾向を調べる場合にも便利です。

---

## 7. まとめと今後の展望

本稿では、**npb_scraping** ライブラリを用いて **NPBの選手成績データ** を取得・活用する方法を紹介しました。npb_scrapingを使うことで、これまで容易に入手しにくかった日本プロ野球の公式成績を自動的に収集し、好きなように分析や可視化を行えます。  
たとえばチーム間で選手の成績を比較したり、長期的なトレンドを調べたりするなど、セイバーメトリクス的なアプローチにも手軽に取り組めるでしょう。特に、NPB公式サイトから直接取得しづらい詳細な年度別成績を、一括でDataFrame化して扱える点は大きな利点です。

一方で、Webスクレイピングに依存するため、データ取得元のBaseball-Referenceのレイアウト変更やURL変更があれば、ライブラリが正常に動作しなくなるリスクがあります。また、公開されている範囲の統計項目以外（守備指標など）は取得できない点や、現時点ではPyPIに未登録でインストールに手間がかかる点など、課題も残されています。

これらに対し、npb_scrapingの開発者は以下のような改良や拡張を検討しています。

- **パッケージ整備と依存関係の明示**: requirements.txt や setup.py を用意し、ライブラリのインストールをより簡単にする（PyPIへの公開も視野）。  
- **守備指標への対応**: 失策数や守備率、UZRのような守備指標を取得対象に加える。  
- **チーム成績の取得**: 個人だけでなくチーム全体の成績（チーム打率やチーム防御率など）も取得できるようにする。  
- **球団名変更への対応**: 球団合併や改名（例：大阪近鉄バファローズ→オリックス・バファローズ）に伴う過去データの扱いを改善する。  

これらが実現すれば **npb_scraping** の有用性はさらに高まるでしょう。  
メジャーリーグ向けには **pybaseball** などのオープンソースライブラリが存在しますが、NPB向けツールはまだ少なく、npb_scraping はそのギャップを埋める貴重な試みと言えます。今後、NPBの公式API公開やデータセット整備などが進む可能性はありますが、それまではこうしたスクレイピングツールが研究・分析を支える重要な手段となるでしょう。  
データ分析に興味のあるプロ野球ファンにとって、npb_scrapingは有力な武器になり得ます。本レポートをきっかけに、ぜひ多様な観点でNPBデータの分析・可視化に挑戦してみてください。  

> **参考**: [GitHub - kirikei4/npb_scraping: NPB data](https://github.com/kirikei4/npb_scraping)

---