系統環境:R 3.4.4 (x64) on Microsoft Windows 10 Ver. 1709

前置作業

本題會使用的 package 有 Lanman / dplyr / magrittr / GGally / ggplot2,先將這些 package include 進來備用

library(Lahman)
library(dplyr)
library(magrittr)
library(GGally)
library(ggplot2)

1-1 請計算每位選手的生涯打擊資料。哪位選手被三振(SO)的次數最多?被三振了幾次?在出場數(G)低於 1000 場的選手中,哪位選手的全壘打數(HR)最多?共打了幾支全壘打?

本題計算的是打擊資料,需對應到 Lanman DB 的 Batting table,第 1 / 2 個問題需要對 SO 進行排序以得到 SO 最大的 playerID

## 只選擇 playerID 及 SO 簡化 data frame,並合併相同 playerID
tbl_batting <- tbl_df(Batting) %>% select(playerID,SO) %>% group_by(playerID) %>% 
  summarise_all(.funs = funs(sum))
## 針對 SO 進行遞減排序
tbl_batting <- tbl_batting[order(tbl_batting$SO,decreasing = TRUE),] 
tbl_batting
  # A tibble: 18,915 x 2
     playerID     SO
     <chr>     <int>
   1 jacksre01  2597
   2 thomeji01  2548
   3 dunnad01   2379
   4 sosasa01   2306
   5 rodrial01  2287
   6 galaran01  2003
   7 cansejo01  1942
   8 stargwi01  1936
   9 camermi01  1901
  10 schmimi01  1883
  # ... with 18,905 more rows

由以上結果得知 jacksre01 被三振次數(SO)最多,共 2597 次。

第 3 / 4 個問題需考慮 G < 1000 的 data,求 HR 最大的 playerID

## 由於 playerID 會有重複的問題,這裡 G < 1000 不使用 raw data 做篩選,改以加總後的結果來判斷
## 只選擇 playerID,G 及 HR 簡化 data frame,並合併相同 playerID
tbl_batting <- tbl_df(Batting) %>% select(playerID,HR,G) %>% group_by(playerID) %>% 
  summarise_all(.funs = funs(sum)) %>% filter(G < 1000)
## 針對 HR 進行遞減排序
tbl_batting <- tbl_batting[order(tbl_batting$HR,decreasing = TRUE),] 
tbl_batting
  # A tibble: 17,350 x 3
     playerID     HR     G
     <chr>     <int> <int>
   1 stantmi03   208   827
   2 balbost01   181   960
   3 gentiji01   179   936
   4 trumbma01   178   849
   5 kittlro01   176   843
   6 hidalri01   171   987
   7 troutmi01   168   811
   8 conigto01   166   876
   9 rodrihe02   160   950
  10 quentca01   154   834
  # ... with 17,340 more rows

由以上結果得知 stantmi03 全壘打數(HR)最多,共 208 次。


1-2 哪位選手其第一次出場比賽(debut)與最後一次出場比賽(finalGame)的間隔時間最久?共隔了幾天?

本題使用 Lanman DB 的 Master table,並計算球員年資,剛好這份資料沒有 playerID 重複的問題,可以直接使用 finalGamedebut 相減,再將結果單獨列為一個 column seniority

## 只選擇 playerID,debut 及 finalGame 簡化資料,並新增欄位 seniority 儲存相減後的天數
tbl_master <- tbl_df(Master) %>% select(playerID,debut,finalGame) %>% 
  mutate(seniority = as.integer( as.Date(finalGame)-as.Date(debut)))
## 針對 seniority 進行遞減排序
tbl_master <- tbl_master[order(tbl_master$seniority,decreasing = TRUE),] 
tbl_master
  # A tibble: 19,105 x 4
     playerID  debut      finalGame  seniority
     <chr>     <chr>      <chr>          <int>
   1 altroni01 1898-07-14 1933-10-01     12862
   2 orourji01 1872-04-26 1904-09-22     11836
   3 minosmi01 1949-04-19 1980-10-05     11492
   4 olearch01 1904-04-14 1934-09-30     11126
   5 lathaar01 1880-07-05 1909-09-30     10678
   6 mcguide01 1884-06-21 1912-05-18     10192
   7 jennihu01 1891-06-01 1918-09-02      9954
   8 eversjo01 1902-09-01 1929-10-06      9897
   9 ryanno01  1966-09-11 1993-09-22      9873
  10 streega01 1904-09-13 1931-09-20      9868
  # ... with 19,095 more rows

由以上結果得知 altroni01 間隔時間最久,共 12862 天。


1-3 請計算2015 年每個球隊的平均薪資,以及2014 年每個球隊的打擊資料(加總),並將兩組資料根據teamID 合併。

本題要求計算平均薪資,需使用 Salaries table

## 找 2015 年的資料,直接將 salary 欄位做平均合併
tbl_salaries <- tbl_df(Salaries) %>% filter(yearID == 2015) %>% select(teamID,salary) %>% group_by(teamID) %>% summarise_all(.funs = funs(mean))
tbl_salaries$salary <- tbl_salaries$salary / 10000
## 原 teamID 形態為 factor,這裡轉為 char 減少 join 問題
tbl_salaries$teamID <- as.character(tbl_salaries$teamID)
tbl_salaries
  # A tibble: 30 x 2
     teamID salary
     <chr>   <dbl>
   1 ARI      213.
   2 ATL      299.
   3 BAL      411.
   4 BOS      566.
   5 CHA      416.
   6 CHN      414.
   7 CIN      419.
   8 CLE      302.
   9 COL      383.
  10 DET      689.
  # ... with 20 more rows

再來是 2014 年每隊的打擊資料,使用 Batting table

## 這裡只需要球隊的資料,因此將 playerID,stint,lgID 及 yearID 捨去
tbl_batting <- tbl_df(Batting) %>% filter(yearID == 2014) %>% select(-playerID,-yearID,-stint,-lgID) %>% group_by(teamID) %>% summarise_all(.funs = funs(sum))
## 原 teamID 形態為 factor,這裡轉為 char 減少 join 問題
tbl_batting$teamID <- as.character(tbl_batting$teamID)
tbl_batting
  # A tibble: 30 x 18
     teamID     G    AB     R     H   X2B   X3B    HR   RBI    SB    CS
     <chr>  <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
   1 ARI     2274  5552   615  1379   259    47   118   573    86    33
   2 ATL     2252  5468   573  1316   240    22   123   545    95    33
   3 BAL     2294  5596   705  1434   264    16   211   681    44    20
   4 BOS     2283  5551   634  1355   282    20   123   601    63    25
   5 CHA     2285  5543   660  1400   279    32   155   625    85    36
   6 CHN     2358  5508   614  1315   270    31   157   590    65    40
   7 CIN     2213  5395   595  1282   254    20   131   562   122    52
   8 CLE     2391  5575   669  1411   284    23   142   644   104    27
   9 COL     2387  5612   755  1551   307    41   186   721    85    48
  10 DET     2330  5630   757  1557   325    26   155   731   106    41
  # ... with 20 more rows, and 7 more variables: BB <int>, SO <int>,
  #   IBB <int>, HBP <int>, SH <int>, SF <int>, GIDP <int>

最後將兩個 table 合併

tbl_salaries <- inner_join(tbl_salaries,tbl_batting, by = "teamID")
tbl_salaries
  # A tibble: 30 x 19
     teamID salary     G    AB     R     H   X2B   X3B    HR   RBI    SB
     <chr>   <dbl> <int> <int> <int> <int> <int> <int> <int> <int> <int>
   1 ARI      213.  2274  5552   615  1379   259    47   118   573    86
   2 ATL      299.  2252  5468   573  1316   240    22   123   545    95
   3 BAL      411.  2294  5596   705  1434   264    16   211   681    44
   4 BOS      566.  2283  5551   634  1355   282    20   123   601    63
   5 CHA      416.  2285  5543   660  1400   279    32   155   625    85
   6 CHN      414.  2358  5508   614  1315   270    31   157   590    65
   7 CIN      419.  2213  5395   595  1282   254    20   131   562   122
   8 CLE      302.  2391  5575   669  1411   284    23   142   644   104
   9 COL      383.  2387  5612   755  1551   307    41   186   721    85
  10 DET      689.  2330  5630   757  1557   325    26   155   731   106
  # ... with 20 more rows, and 8 more variables: CS <int>, BB <int>,
  #   SO <int>, IBB <int>, HBP <int>, SH <int>, SF <int>, GIDP <int>

1-4 根據3 所得到的資料,使用ggpairs 繪製各球隊平均薪資與安打數(H)、全壘打數(HR)、打點數(RBI)、盜壘數(SB)、三振次數(SO)總數的散布圖。

tbl_salaries %>% 
  ggpairs(columns = c("salary","H","HR","RBI","SB","SO"),lower = list(continuous = "smooth"))

## 刪除產生的變數
rm(tbl_batting)
rm(tbl_master)
rm(tbl_salaries)