300億円欲しい

メジャーリーグのデータ解析します

メジャーリーグのデータ解析をしたい (K/BBの計算したら上原が凄い)

序論

Rを使ってメジャーリーグのデータ処理をします.
今回は前処理に役立つplyrパッケージを使いながら,
レッドソックス上原浩治選手の成績を確認します.

今回使うのは, plyrパッケージです.
データのまとめにはとても便利です.
ddplyの使い方がわかると思います.


データの取得と指標の確認

データはlahmanのdatabaseを使います.
せっかくだから最新のバージョンを使います.

http://www.seanlahman.com/baseball-archive/statistics/


K/BBについて.
今年はレッドソックスのリリーバー上原浩治選手が大活躍でした.
最初は中継ぎ投手でしたが, 後半からは安定した守護神として勝利に貢献していました.

安定したピッチングをする投手を評価する指標として, K/BBというものがあります.
Kは奪三振(Knock out), BBは四球(Base on Balls)です.
奪三振数 / 四球数 で計算されます.

Wikipediaより... K/BBの説明

奪三振と与四球は守備や球場の影響を受けないため、K/BBはシーズン毎のバラつきが小幅で、投手の制球力を示す。 また、好投手ならば一般的にK/BBが2.00を下回る事が少なく[1]、優秀な投手は3.50を超える事が多い。

フォアボールが少なく, 三振が多く取れるピッチングをするとK/BBは高くなります.
しっかりコントロールしながら三振が取れる選手が評価できます.

コントロールを重視すると球威が落ちて三振が取れません.
三振を重視すると, 球威のためにコントロールが落ちて四球が増えます.
K/BBはなかなか奥深い指標です.

通算K/BBの計算

今回はPitching.csvを使います.
Pitchingデータの内容を確認します.

> Pitching <- read.csv("Pitching.csv")
> head(Pitching)
   playerID yearID stint teamID lgID  W  L  G GS CG SHO SV IPouts   H  ER HR BB SO BAOpp   ERA IBB WP HBP BK BFP GF   R SH SF GIDP
1 bechtge01   1871     1    PH1 <NA>  1  2  3  3  2   0  0     78  43  23  0 11  1    NA  7.96  NA NA  NA  0  NA NA  42 NA NA   NA
2 brainas01   1871     1    WS3 <NA> 12 15 30 30 30   0  0    792 361 132  4 37 13    NA  4.50  NA NA  NA  0  NA NA 292 NA NA   NA
3 fergubo01   1871     1    NY2 <NA>  0  0  1  0  0   0  0      3   8   3  0  0  0    NA 27.00  NA NA  NA  0  NA NA   9 NA NA   NA
4 fishech01   1871     1    RC1 <NA>  4 16 24 24 22   1  0    639 295 103  3 31 15    NA  4.35  NA NA  NA  0  NA NA 257 NA NA   NA
5 fleetfr01   1871     1    NY2 <NA>  0  1  1  1  1   0  0     27  20  10  0  3  0    NA 10.00  NA NA  NA  0  NA NA  21 NA NA   NA
6 flowedi01   1871     1    TRO <NA>  0  0  1  0  0   0  0      3   1   0  0  0  0    NA  0.00  NA NA  NA  0  NA NA   0 NA NA   NA
> 

なるほど.
SOが奪三振, BBが四球ですね.

では, 通算SOと通算BB を計算して, 通算K/BBを調べてみます.

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

# 重いので2000年以降に限る
Pitching <- subset(Pitching, yearID> 2000)

# plyrを使ってデータを要約
Pitching.KBB <- ddply(Pitching, .(playerID), summarize, 
                      Career.SO = sum(SO, na.rm = TRUE), Career.BB = sum(BB, na.rm=TRUE), 
                      Career.IPouts = sum(IPouts, na.rm = TRUE),
                      Career.KBB = sum(SO, na.rm=TRUE)/ sum(BB, na.rm = TRUE))

内容を確認します.

> head(Pitching.KBB)
   playerID Career.SO Career.BB Career.IPouts Career.KBB
1 aardsda01       305       169           919   1.804734
2  abadfe01        97        43           367   2.255814
3 abbotpa01       218       191           999   1.141361
4 abreuju01        12         3            20   4.000000
5 abreuwi01        38        19           133   2.000000
6 accarje01       205       111           854   1.846847

投球回が少ないために四球0で引退した残念な選手もいますので,
100イニング以上投げた投手に限定して, 通算K/BBのランキングを見ます

# 四球1以上でアウトを300個以上とった選手
Pitching.KBB <- subset(Pitching.KBB, Career.BB > 0 & Career.IPouts >= 300)

# K/BBで並べ替え
Pitching.KBB <- Pitching.KBB[order(Pitching.KBB$Career.KBB, decreasing = TRUE), ]

確認します.

> head(Pitching.KBB)
      playerID Career.SO Career.BB Career.IPouts Career.KBB
1947 ueharko01       332        38           858   8.736842
1723 schilcu01      1377       212          4077   6.495283
1644  romose01       335        60           881   5.583333
1601 riverma01       778       142          2494   5.478873
1296 mujiced01       350        68          1318   5.147059
497  doolise01       120        24           349   5.000000

ueharako01 ... 一体何者なんだ...
せっかくだから可視化します. 上位10人だけ考えます.

ただのplotではなくてggplot2します.

library(ggplot2)


Pitching.KBB.top10 <- head(Pitching.KBB, 10)

ggplot(Pitching.KBB.top10, aes(x = playerID, y = Career.KBB)) +  geom_bar(stat="identity")

こんな感じです.
f:id:gg_hatano:20140110092758p:plain

上原すごいですね.

以上です.

plyrパッケージについて

これを読みます.
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
http://www.slideshare.net/teramonagi/tokyo-r30-20130420
よくわかりました.

plyrは, 分割して, 処理して, まとめます,

コードを見返してみると,

Pitching.KBB <- ddply(Pitching, .(playerID), summarize, 
                      Career.SO = sum(SO, na.rm = TRUE), Career.BB = sum(BB, na.rm=TRUE), 
                      Career.IPouts = sum(IPouts, na.rm = TRUE),
                      Career.KBB = sum(SO, na.rm=TRUE)/ sum(BB, na.rm = TRUE))

となっています.

playerIDで分割して, 選手ごとの成績データフレームが得られます.
選手の成績でsumを取れば, 通算成績になります.

plyrの練習...年度別チーム防御率の算出

もう少し遊んでみます.
年度別チーム防御率ランキングを作ります.

手順としては,
1. plyrで, チームと年度で分割して, 各選手のデータで和を取る.
2. 合計自責点と合計投球回から防御率を計算.
3. 防御率で並べ替え
ですが, コードはこんな感じになります.

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

# 2000年以降
Pitching <- subset(Pitching, yearID > 2000)

# チーム防御率を計算
# teamIDとyearIDで分割して成績を統合すればいい
# 1アウトあたり失点 × 27 で防御率になる
Pitching.teamERA <- ddply(Pitching, .(teamID, yearID), summarize, 
                          teamIPouts = sum(IPouts, na.rm=TRUE), 
                          teamER = sum(ER, na.rm=TRUE), 
                          teamERA = teamER / teamIPouts * 27) 
head(Pitching.teamERA)

# 並べ替え
Pitching.teamERA.ordered <- Pitching.teamERA[order(Pitching.teamERA$teamERA), ]

結果を見ます.

> head(Pitching.teamERA.ordered)
    teamID yearID teamIPouts teamER  teamERA
275    PHI   2011       4431    496 3.022343
19     ATL   2002       4402    511 3.134257
183    LAN   2003       4373    511 3.155042
30     ATL   2013       4351    512 3.177201
354    TBA   2012       4379    518 3.193880
327    SFN   2011       4404    523 3.206403

簡単に出来ました. 年度とチームで分割してまとめただけです.
plyrを上手に使うと楽しいです.

... 2011年のフィリーズはチーム防御率3.02...???

"野球の記録で話したい"
3本柱は太かった フィラデルフィア・フィリーズ2011年投手|2011年MLBレビュー
http://baseballstats2011.jp/archives/889585.html

すごいわ.

追記

データの数値による並べ替えはarrange関数でいいですね.
わざわざorderでゴニョゴニョやるのは面倒です.

Pitching.teamERA.ordered <- arrange(Pitching.teamERA, teamERA)

の方が簡単です.