初めてのスクレイピング

スクレイピングとぞいふもの

へー,webからデータを取ってくることをスクレイピングっていうんだ,というレベルから始めたのですがね。

毎年,データ演習の授業では色々なデータを使うのだけど,分布が偏ってるのもあって,適度に関係性が見られて,カテゴリカル変数もあって,それでいて身近な例で,というような丁度いいデータってのが欲しいもんなのですよ。

なので私はいつも,プロ野球データFreak さんのデータをコピペして,データを作っていました。
が,これが簡単にできるパッケージがあるらしい。のでやってみた。

library(rvest)
p.data <- read_html("http://baseball-data.com/ranking-salary/all/p.html") #ピッチャーの年俸など
h.data <- read_html("http://baseball-data.com/ranking-salary/all/h.html") #野手のそれ
avg5 <- read_html("http://baseball-data.com/stats/hitter2-all/avg-5.html") #規定打数1/3以上の打者基本成績
era5 <- read_html("http://baseball-data.com/stats/pitcher2-all/era-5.html") #規定投球回1/3以上の投手基本成績
p.df <- as.data.frame(html_table(p.data,head=T))
head(p.df)
##   順位     選手名       チーム 年俸.推定. 守備 年数 年齢   生年月日  身長 体重 血液型 投打 出身地
## 1    1 杉内 俊哉         巨人 50,000万円 投手 14年 34歳 1980/10/30 175cm 82kg    A型 左左   福岡
## 2    1 金子 千尋   オリックス 50,000万円 投手 11年 31歳 1983/11/08 180cm 77kg    O型 右左   新潟
## 3    3 内海 哲也         巨人 40,000万円 投手 12年 33歳 1982/04/29 186cm 93kg    A型 左左   京都
## 4    3 松坂 大輔 ソフトバンク 40,000万円 投手  9年 35歳 1980/09/13 183cm 93kg    O型 右右   東京
## 5    3 黒田 博樹         広島 40,000万円 投手 12年 40歳 1975/02/10 185cm 93kg    B型 右右   大阪
## 6    3   攝津 正 ソフトバンク 40,000万円 投手  7年 33歳 1982/06/01 181cm 97kg    O型 右右   秋田

同様に読み込んでデータ化していけばいいんだけど,残念ながらデータによっては数字じゃないところがあったり,最後にも変数名が入っていたりして,全部chr型になってたりする。

面倒だけど,これを修正する作業を行いました。

ピッチャーの年俸データを整える

文字列操作パッケージstringrの解説を参考に,文字列操作をしていく。

library(stringr) # 文字列操作パッケージ
p.df$順位 <- NULL
p.df$チーム <- as.factor(p.df$チーム) # チーム名はfactor型
#年俸の「万円」と「,」を除外して数字に
p.df$年俸.推定. <- str_replace(p.df$年俸.推定.,"万円","") %>% str_replace(",","") %>% as.numeric() 
p.df$年数 <- str_replace(p.df$年数,"年","") %>% as.numeric() #年数の「年」を除外して数字に
p.df$年齢 <- str_replace(p.df$年齢,"歳","") %>% as.numeric() #年齢の「歳」を除外して数字に
# 生年月日を"/"で区切って数値データにし,行列に組み上げてからデータフレームとして元データに結合
birth.data <- p.df$生年月日 %>% str_split("/") %>% unlist()  %>% as.numeric() %>% matrix(ncol=3,byrow=T) %>% as.data.frame()
p.df <- cbind(p.df,birth.data)
p.df$身長 <- str_replace(p.df$身長,"cm","") %>% as.numeric() #身長の「cm」を除外して数字に
p.df$体重 <- str_replace(p.df$体重,"kg","") %>% as.numeric() #体重の「kg」を除外して数字に1
p.df$血液型 <- as.factor(p.df$血液型)
p.df$投 <- str_sub(p.df$投打, start=1, end=1) %>% as.factor() #投げる腕を切り出してfactor型に
p.df$打 <- str_sub(p.df$投打, start=2, end=2) %>% as.factor() #打つ腕を切り出してfactor型に
p.df$出身地 <- as.factor(p.df$出身地)
p.df$守備 <- NULL #データを作り変えた変数は除外しておく
p.df$生年月日 <- NULL
p.df$投打 <- NULL
# 変数名を英語にしておく
names(p.df) <- c("name","team","pay","year","age","height","weight","blood","home","BirthY","BirthM","BirthD","throw","hit")
summary(p.df) # 確認
##      name                     team         pay             year           age            height          weight      
##  Length:100         ソフトバンク:15   Min.   : 4200   Min.   : 1.0   Min.   :21.00   Min.   :167.0   Min.   : 67.00  
##  Class :character   巨人        :12   1st Qu.: 6000   1st Qu.: 4.0   1st Qu.:29.00   1st Qu.:179.0   1st Qu.: 80.00  
##  Mode  :character   オリックス  :10   Median : 9000   Median : 8.0   Median :31.00   Median :181.5   Median : 86.00  
##                     ヤクルト    : 9   Mean   :12579   Mean   : 8.1   Mean   :31.53   Mean   :183.2   Mean   : 88.27  
##                     日本ハム    : 9   3rd Qu.:15000   3rd Qu.:12.0   3rd Qu.:34.25   3rd Qu.:186.2   3rd Qu.: 95.25  
##                     DeNA        : 7   Max.   :50000   Max.   :24.0   Max.   :45.00   Max.   :205.0   Max.   :121.00  
##                     (Other)     :38                                                                                  
##   blood          home        BirthY         BirthM          BirthD      throw   hit    
##  AB型: 5   アメリカ:16   Min.   :1970   Min.   : 1.00   Min.   : 1.00   右:76   右:71  
##  A型 :34   福岡    : 8   1st Qu.:1980   1st Qu.: 5.00   1st Qu.: 9.00   左:24   左:29  
##  B型 :15   愛知    : 6   Median :1983   Median : 7.00   Median :14.00                  
##  O型 :22   京都    : 6   Mean   :1983   Mean   : 7.35   Mean   :15.75                  
##  不明:24   大阪    : 6   3rd Qu.:1986   3rd Qu.:10.00   3rd Qu.:24.25                  
##            広島    : 4   Max.   :1994   Max.   :12.00   Max.   :31.00                  
##            (Other) :54

バッターの年俸データを整える

同じような作業。

h.df <- as.data.frame(html_table(h.data,head=T))
h.df$順位 <- NULL
h.df$チーム <- as.factor(h.df$チーム) # チーム名はfactor型
#年俸の「万円」と「,」を除外して数字に
h.df$年俸.推定. <- str_replace(h.df$年俸.推定.,"万円","") %>% str_replace(",","") %>% as.numeric() 
h.df$年数 <- str_replace(h.df$年数,"年","") %>% as.numeric() #年数の「年」を除外して数字に
h.df$年齢 <- str_replace(h.df$年齢,"歳","") %>% as.numeric() #年齢の「歳」を除外して数字に
# 生年月日を"/"で区切って数値データにし,行列に組み上げてからデータフレームとして元データに結合
birth.data <- h.df$生年月日 %>% str_split("/") %>% unlist()  %>% as.numeric() %>% matrix(ncol=3,byrow=T) %>% as.data.frame()
h.df <- cbind(h.df,birth.data)
h.df$身長 <- str_replace(h.df$身長,"cm","") %>% as.numeric() #身長の「cm」を除外して数字に
h.df$体重 <- str_replace(h.df$体重,"kg","") %>% as.numeric() #体重の「kg」を除外して数字に1
h.df$血液型 <- as.factor(h.df$血液型)
h.df$投 <- str_sub(h.df$投打, start=1, end=1) %>% as.factor() #投げる腕を切り出してfactor型に
h.df$打 <- str_sub(h.df$投打, start=2, end=2) %>% as.factor() #打つ腕を切り出してfactor型に
h.df$出身地 <- as.factor(h.df$出身地)
h.df$守備 <- NULL #データを作り変えた変数は除外しておく
h.df$生年月日 <- NULL
h.df$投打 <- NULL
names(h.df) <- c("name","team","pay","year","age","height","weight","blood","home","BirthY","BirthM","BirthD","throw","hit")
summary(h.df) # 確認
##      name                     team         pay             year            age            height          weight      
##  Length:100         巨人        :12   Min.   : 4800   Min.   : 1.00   Min.   :21.00   Min.   :169.0   Min.   : 67.00  
##  Class :character   ソフトバンク:11   1st Qu.: 7200   1st Qu.: 4.00   1st Qu.:28.00   1st Qu.:177.0   1st Qu.: 79.75  
##  Mode  :character   オリックス  :10   Median :10000   Median : 9.50   Median :32.00   Median :180.0   Median : 88.00  
##                     楽天        :10   Mean   :14342   Mean   : 9.28   Mean   :31.78   Mean   :180.8   Mean   : 88.43  
##                     ヤクルト    : 8   3rd Qu.:18500   3rd Qu.:13.00   3rd Qu.:35.00   3rd Qu.:185.0   3rd Qu.: 95.00  
##                     ロッテ      : 8   Max.   :51000   Max.   :27.00   Max.   :44.00   Max.   :198.0   Max.   :130.00  
##                     (Other)     :41                                                                                   
##   blood                home        BirthY         BirthM          BirthD      throw   hit    
##  AB型: 8   アメリカ      : 9   Min.   :1970   Min.   : 1.00   Min.   : 1.00   右:95   右:60  
##  A型 :26   大阪          : 7   1st Qu.:1980   1st Qu.: 4.00   1st Qu.: 7.75   左: 5   左:36  
##  B型 :17   ドミニカ共和国: 6   Median :1983   Median : 7.00   Median :15.00           両: 4  
##  O型 :28   東京          : 6   Mean   :1983   Mean   : 6.68   Mean   :15.29                  
##  不明:21   神奈川        : 5   3rd Qu.:1987   3rd Qu.: 9.00   3rd Qu.:23.00                  
##            千葉          : 5   Max.   :1994   Max.   :12.00   Max.   :31.00                  
##            (Other)       :62

成績のデータを整える。

最後の一行に変なのが入っているせいで全部キャラクターになっちゃってる。

#打者
avg5.df <- as.data.frame(html_table(avg5,head=T))
avg5.df <- avg5.df[-nrow(avg5.df),]
avg5.df$順位 <- NULL
avg5.df$チーム <- as.factor(avg5.df$チーム)
avg5.df[3:24] <- apply(avg5.df[3:24],2,as.numeric) #あとは数字変数
# 変数名の変更
#  "選手名" "チーム" "打率"   "試合"   "打席数" "打数"   "得点"   "安打"   "二塁打" "三塁打" "本塁打" "塁打"  
#  "打点"   "盗塁"   "盗塁刺" "犠打"   "犠飛"   "四球"   "敬遠"   "死球"   "三振"   "併殺打" "長打率" "出塁率"
names(avg5.df) <- c("name","team","BA","games","PA","AB","R","Hit","Double","Three","HR","TB",
                    "RBI","steal","CS","SH","SF","BB","HWHI","HBP","K","DP","SLG","OBP")

#投手
era5.df <- as.data.frame(html_table(era5,head=T))
era5.df <- era5.df[-nrow(era5.df),]
era5.df$順位 <- NULL
era5.df$チーム <- as.factor(era5.df$チーム)
era5.df[3:25] <- apply(era5.df[3:25],2,as.numeric) #あとは数字変数
# 変数名の変更
#  "選手名"   "チーム"   "防御率"   "試合"     "勝利"     "敗北"     "セlブ"    "ホlルド"  "HP"      
#  "完投"     "完封勝"   "無四球"   "勝率"     "打者"     "投球回"   "被安打"   "被本塁打" "与四球"   "敬遠"    
#  "与死球"   "奪三振"   "暴投"     "ボlク"    "失点"     "自責点"
names(era5.df) <- c("name","team","ERA","games","win","lose","save","hold","HP",
                    "CG","SHO","No.walks","win.rate","batter","times","hits","HR","BB","HWHI",
                    "DB","K","W.pitch","balk","R","ER")

成績と年棒を合わせる

ホームラン一本おいくら万円とか知りたいじゃないですか。
名前でマージします。

batter <- merge(h.df,avg5.df,by="name")
pitcher <- merge(p.df,era5.df,by="name")

これで出来上がり。あとはwrite.tableでもなんでもどうぞー。