Welcome to the ballr [baw-ler], as in baller1. This is the R resource for your basketball-reference.com needs.
library(devtools)
devtools::install_github("rtelmore/ballr")
library(ballr)
library(magrittr)
library(ggplot2)
library(janitor)
library(scales)
Current standings
standings <- NBAStandingsByDate() # "YEAR-MO-DY"
standings
## $East
## eastern_conference w l w_lpercent gb pw pl ps_g pa_g
## 1 Boston Celtics 11 2 0.846 — 10 3 102.8 94.0
## 2 Detroit Pistons 9 3 0.750 1.5 8 4 106.1 101.1
## 3 Orlando Magic 8 5 0.615 3 8 5 110.5 107.6
## 4 Toronto Raptors 7 4 0.636 3 7 4 110.1 105.2
## 5 New York Knicks 7 5 0.583 3.5 7 5 106.4 105.0
## 6 Washington Wizards 7 5 0.583 3.5 8 4 111.5 107.1
## 7 Milwaukee Bucks 6 6 0.500 4.5 5 7 103.8 105.3
## 8 Philadelphia 76ers 6 6 0.500 4.5 5 7 107.9 109.8
## 9 Miami Heat 6 6 0.500 4.5 6 6 101.8 102.3
## 10 Cleveland Cavaliers 6 7 0.462 5 5 8 110.2 113.4
## 11 Indiana Pacers 6 7 0.462 5 7 6 109.0 108.4
## 12 Charlotte Hornets 5 7 0.417 5.5 5 7 103.4 104.9
## 13 Brooklyn Nets 5 8 0.385 6 5 8 110.6 114.5
## 14 Chicago Bulls 2 9 0.182 8 2 9 93.6 103.9
## 15 Atlanta Hawks 2 11 0.154 9 3 10 102.5 110.8
##
## $West
## western_conference w l w_lpercent gb pw pl ps_g pa_g
## 1 Houston Rockets 10 3 0.769 — 9 4 110.5 103.5
## 2 Golden State Warriors 10 3 0.769 — 11 2 120.3 108.3
## 3 San Antonio Spurs 8 5 0.615 2 8 5 103.0 99.6
## 4 Denver Nuggets 8 5 0.615 2 8 5 107.6 105.2
## 5 Memphis Grizzlies 7 5 0.583 2.5 7 5 101.0 99.1
## 6 Minnesota Timberwolves 7 5 0.583 2.5 5 7 108.8 111.8
## 7 New Orleans Pelicans 7 6 0.538 3 7 6 107.5 107.2
## 8 Portland Trail Blazers 6 6 0.500 3.5 8 4 105.5 100.7
## 9 Utah Jazz 6 7 0.462 4 6 7 98.3 99.6
## 10 Los Angeles Clippers 5 7 0.417 4.5 7 5 107.4 105.8
## 11 Oklahoma City Thunder 5 7 0.417 4.5 8 4 103.3 98.4
## 12 Los Angeles Lakers 5 8 0.385 5 5 8 103.5 106.8
## 13 Phoenix Suns 5 9 0.357 5.5 3 11 107.0 116.2
## 14 Sacramento Kings 3 9 0.250 6.5 2 10 94.8 105.3
## 15 Dallas Mavericks 2 11 0.154 8 3 10 99.5 107.4
Standings on an arbitrary date
standings <- NBAStandingsByDate("2015-12-31")
standings
## $East
## eastern_conference w l w_lpercent gb pw pl ps_g pa_g
## 1 Cleveland Cavaliers* 21 9 0.700 — 20 10 99.7 95.1
## 2 Atlanta Hawks* 21 13 0.618 2 19 15 102.0 100.1
## 3 Toronto Raptors* 20 13 0.606 2.5 20 13 99.8 96.4
## 4 Chicago Bulls 18 12 0.600 3 16 14 101.1 100.0
## 5 Orlando Magic 19 13 0.594 3 19 13 101.0 98.4
## 6 Miami Heat* 18 13 0.581 3.5 17 14 97.0 95.5
## 7 Indiana Pacers* 18 13 0.581 3.5 20 11 102.3 98.5
## 8 Boston Celtics* 18 14 0.563 4 20 12 103.1 99.1
## 9 Charlotte Hornets* 17 14 0.548 4.5 18 13 102.5 99.7
## 10 Detroit Pistons* 17 15 0.531 5 17 15 101.0 100.2
## 11 New York Knicks 15 18 0.455 7.5 15 18 98.0 99.5
## 12 Washington Wizards 14 16 0.467 7 12 18 101.5 104.4
## 13 Milwaukee Bucks 12 21 0.364 10.5 10 23 97.1 103.2
## 14 Brooklyn Nets 9 23 0.281 13 9 23 97.1 103.4
## 15 Philadelphia 76ers 3 31 0.088 20 5 29 92.5 104.4
##
## $West
## western_conference w l w_lpercent gb pw pl ps_g pa_g
## 1 Golden State Warriors* 29 2 0.935 — 26 5 114.1 101.8
## 2 San Antonio Spurs* 28 6 0.824 2.5 30 4 102.0 88.6
## 3 Oklahoma City Thunder* 22 10 0.688 7.5 24 8 108.6 100.4
## 4 Los Angeles Clippers* 20 13 0.606 10 19 14 103.1 100.9
## 5 Dallas Mavericks* 19 13 0.594 10.5 18 14 102.3 100.8
## 6 Memphis Grizzlies* 18 16 0.529 12.5 13 21 96.4 99.4
## 7 Houston Rockets* 16 17 0.485 14 15 18 104.1 105.5
## 8 Portland Trail Blazers* 14 20 0.412 16.5 16 18 101.3 102.0
## 9 Utah Jazz 13 17 0.433 15.5 14 16 96.6 97.3
## 10 Minnesota Timberwolves 12 20 0.375 17.5 14 18 100.4 102.6
## 11 Sacramento Kings 12 20 0.375 17.5 13 19 104.2 107.3
## 12 Denver Nuggets 12 21 0.364 18 11 22 98.9 103.8
## 13 Phoenix Suns 12 22 0.353 18.5 14 20 102.7 105.4
## 14 New Orleans Pelicans 10 21 0.323 19 11 20 102.1 107.0
## 15 Los Angeles Lakers 6 27 0.182 24 6 27 96.8 107.2
players <- NBAPerGameStatistics()
players
## # A tibble: 437 x 31
## rk player pos age tm g gs mp fg fga
## <dbl> <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 Alex Abrines SG 24 OKC 12 0 16.7 1.5 3.8
## 2 2 Quincy Acy PF 27 BRK 10 0 17.6 1.7 4.8
## 3 3 Steven Adams C 24 OKC 11 11 30.7 5.3 8.1
## 4 4 Bam Adebayo C 20 MIA 8 3 14.0 1.4 2.9
## 5 5 Arron Afflalo SG 32 ORL 9 0 9.4 0.4 1.7
## 6 6 Cole Aldrich C 29 MIN 4 0 2.3 0.0 0.5
## 7 7 LaMarcus Aldridge PF 32 SAS 13 13 32.8 8.5 16.9
## 8 8 Jarrett Allen C 19 BRK 6 0 15.0 1.5 3.7
## 9 9 Tony Allen SG 36 NOP 12 0 13.5 2.3 4.5
## 10 10 Al-Farouq Aminu PF 27 POR 8 8 30.1 3.3 7.5
## # ... with 427 more rows, and 21 more variables: fgpercent <dbl>,
## # x3p <dbl>, x3pa <dbl>, x3ppercent <dbl>, x2p <dbl>, x2pa <dbl>,
## # x2ppercent <dbl>, efgpercent <dbl>, ft <dbl>, fta <dbl>,
## # ftpercent <dbl>, orb <dbl>, drb <dbl>, trb <dbl>, ast <dbl>,
## # stl <dbl>, blk <dbl>, tov <dbl>, pf <dbl>, ps_g <dbl>, link <chr>
players <- NBAPerGameStatistics(season = 2017)
players %>%
dplyr::filter(mp > 20, pos %in% c("SF")) %>%
dplyr::select(player, link) %>%
dplyr::distinct()
## # A tibble: 56 x 2
## player link
## <chr> <chr>
## 1 Al-Farouq Aminu /players/a/aminual01.html
## 2 Justin Anderson /players/a/anderju01.html
## 3 Giannis Antetokounmpo /players/a/antetgi01.html
## 4 Carmelo Anthony /players/a/anthoca01.html
## 5 Trevor Ariza /players/a/arizatr01.html
## 6 Matt Barnes /players/b/barnema02.html
## 7 Kent Bazemore /players/b/bazemke01.html
## 8 Bojan Bogdanovic /players/b/bogdabo02.html
## 9 Jimmy Butler /players/b/butleji01.html
## 10 DeMarre Carroll /players/c/carrode01.html
## # ... with 46 more rows
players <- NBAPerGameStatisticsPer36Min(season = 2017)
players
## # A tibble: 595 x 30
## rk player pos age tm g gs mp fg fga
## <dbl> <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 Alex Abrines SG 23 OKC 68 6 1055 4.6 11.6
## 2 2 Quincy Acy PF 26 TOT 38 1 558 4.5 11.0
## 3 2 Quincy Acy PF 26 DAL 6 0 48 3.7 12.7
## 4 2 Quincy Acy PF 26 BRK 32 1 510 4.6 10.8
## 5 3 Steven Adams C 23 OKC 80 80 2389 5.6 9.9
## 6 4 Arron Afflalo SG 31 SAC 61 45 1580 4.2 9.6
## 7 5 Alexis Ajinca C 28 NOP 39 15 584 5.5 11.0
## 8 6 Cole Aldrich C 28 MIN 62 0 531 3.1 5.8
## 9 7 LaMarcus Aldridge PF 31 SAS 72 72 2335 7.7 16.2
## 10 8 Lavoy Allen PF 27 IND 61 5 871 3.2 6.9
## # ... with 585 more rows, and 20 more variables: fgpercent <dbl>,
## # x3p <dbl>, x3pa <dbl>, x3ppercent <dbl>, x2p <dbl>, x2pa <dbl>,
## # x2ppercent <dbl>, ft <dbl>, fta <dbl>, ftpercent <dbl>, orb <dbl>,
## # drb <dbl>, trb <dbl>, ast <dbl>, stl <dbl>, blk <dbl>, tov <dbl>,
## # pf <dbl>, pts <dbl>, link <chr>
players <- NBAPerGameStatisticsPer36Min(season = 2017) %>%
dplyr::filter(pos %in% c("C", "PF")) %>%
dplyr::top_n(n = 10, pts) %>%
dplyr::select(player, link) %>%
dplyr::distinct()
players
## # A tibble: 8 x 2
## player link
## <chr> <chr>
## 1 DeMarcus Cousins /players/c/couside01.html
## 2 Anthony Davis /players/d/davisan02.html
## 3 Joel Embiid /players/e/embiijo01.html
## 4 Enes Kanter /players/k/kanteen01.html
## 5 Brook Lopez /players/l/lopezbr01.html
## 6 Boban Marjanovic /players/m/marjabo01.html
## 7 JaVale McGee /players/m/mcgeeja01.html
## 8 Karl-Anthony Towns /players/t/townska01.html
Query each player in the list
player_stats <- NBAPlayerPerGameStats(players[1, 2]) %>%
dplyr::filter(!is.na(age)) %>%
dplyr::mutate(player = as.character(players[1, 1]))
Append the stats from each player into a df
for(i in 2:dim(players)[1]){
tmp <- NBAPlayerPerGameStats(players[i, 2]) %>%
dplyr::filter(!is.na(age)) %>%
dplyr::mutate(player = as.character(players[i, 1]))
player_stats <- dplyr::bind_rows(player_stats, tmp)
}
Plot everything
#player_stats <- clean_names(player_stats)
p <- ggplot2::ggplot(data = player_stats,
aes(x = age, y = efgpercent, group = player))
p + ggplot2::geom_line(alpha = .25) +
ggplot2::geom_point(alpha = .25) +
ggplot2::scale_y_continuous("effective field goal %age", limit = c(0, 1),
labels = percent) +
ggplot2::geom_line(data = dplyr::filter(player_stats, player == "Anthony Davis"),
aes(x = age, y = efgpercent), size = 1, col = "#1f78b4") +
ggplot2::geom_point(data = dplyr::filter(player_stats, player == "Anthony Davis"),
aes(x = age, y = efgpercent), size = 1, col = "#1f78b4") +
ggplot2::geom_line(data = dplyr::filter(player_stats, player == "DeMarcus Cousins"),
aes(x = age, y = efgpercent), size = 1, col = "#33a02c") +
ggplot2::geom_point(data = dplyr::filter(player_stats, player == "DeMarcus Cousins"),
aes(x = age, y = efgpercent), size = 1, col = "#33a02c") +
ggplot2::theme_bw()
per_100 <- NBAPerGameStatisticsPer100Poss(season = 2018)
utils::head(per_100)
## rk player pos age tm g gs mp fg fga fgpercent x3p x3pa
## 1 1 Alex Abrines SG 24 OKC 12 0 200 4.5 11.1 0.400 2.7 7.4
## 2 2 Quincy Acy PF 27 BRK 10 0 176 4.4 12.4 0.354 3.9 10.9
## 3 3 Steven Adams C 24 OKC 11 11 338 8.5 13.0 0.652 0.0 0.0
## 4 4 Bam Adebayo C 20 MIA 8 3 112 4.8 10.0 0.478 0.0 0.0
## 5 5 Arron Afflalo SG 32 ORL 9 0 85 2.2 8.3 0.267 0.6 3.3
## 6 6 Cole Aldrich C 29 MIN 4 0 9 0.0 10.7 0.000 0.0 0.0
## x3ppercent x2p x2pa x2ppercent ft fta ftpercent orb drb trb ast stl
## 1 0.367 1.7 3.7 0.467 1.5 1.7 0.857 1.2 3.2 4.5 1.2 1.7
## 2 0.357 0.5 1.6 0.333 2.1 2.6 0.800 1.0 9.8 10.9 2.1 1.3
## 3 NA 8.5 13.0 0.652 2.8 3.7 0.760 6.4 7.0 13.5 1.9 2.5
## 4 NA 4.8 10.0 0.478 3.5 4.8 0.727 6.1 9.2 15.3 0.0 1.7
## 5 0.167 1.7 5.0 0.333 2.2 2.8 0.800 0.0 6.1 6.1 2.8 0.6
## 6 NA 0.0 10.7 0.000 5.4 10.7 0.500 0.0 5.4 5.4 5.4 5.4
## blk tov pf pts x ortg drtg link
## 1 0.2 1.2 6.4 13.1 NA 110 106 /players/a/abrinal01.html
## 2 0.0 2.9 6.5 14.8 NA 97 109 /players/a/acyqu01.html
## 3 2.0 2.8 3.5 19.8 NA 127 100 /players/a/adamsst01.html
## 4 1.7 1.3 5.2 13.1 NA 117 101 /players/a/adebaba01.html
## 5 0.6 1.7 2.8 7.2 NA 79 109 /players/a/afflaar01.html
## 6 0.0 0.0 10.7 5.4 NA 59 105 /players/a/aldrico01.html
adv_stats <- NBAPerGameAdvStatistics(season = 2018)
utils::head(adv_stats)
## rk player pos age tm g mp per tspercent x3par ftr
## 1 1 Alex Abrines SG 24 OKC 12 200 7.5 0.551 0.667 0.156
## 2 2 Quincy Acy PF 27 BRK 10 176 7.5 0.544 0.875 0.208
## 3 3 Steven Adams C 24 OKC 11 338 21.9 0.675 0.000 0.281
## 4 4 Bam Adebayo C 20 MIA 8 112 14.4 0.539 0.000 0.478
## 5 5 Arron Afflalo SG 32 ORL 9 85 2.8 0.378 0.400 0.333
## 6 6 Cole Aldrich C 29 MIN 4 9 0.9 0.174 0.000 1.000
## orbpercent drbpercent trbpercent astpercent stlpercent blkpercent
## 1 2.7 7.5 5.1 3.5 1.7 0.4
## 2 2.2 22.7 12.1 6.3 1.3 0.0
## 3 14.3 16.3 15.3 6.1 2.5 3.7
## 4 14.2 20.0 17.2 0.0 1.7 2.8
## 5 0.0 13.7 7.1 7.3 0.6 0.9
## 6 0.0 13.1 6.4 13.5 5.4 0.0
## tovpercent usgpercent x ows dws ws ws_48 x_2 obpm dbpm bpm vorp
## 1 9.4 11.5 NA 0.2 0.2 0.4 0.091 NA -1.4 -0.7 -2.1 0.0
## 2 17.4 14.6 NA 0.0 0.1 0.1 0.031 NA -2.3 -1.0 -3.3 -0.1
## 3 16.0 15.3 NA 1.0 0.6 1.6 0.225 NA 1.8 3.1 4.9 0.6
## 4 9.7 12.1 NA 0.2 0.2 0.4 0.153 NA -3.7 -1.1 -4.8 -0.1
## 5 14.9 10.2 NA -0.1 0.1 0.0 -0.025 NA -5.5 -0.2 -5.7 -0.1
## 6 0.0 13.6 NA 0.0 0.0 0.0 -0.088 NA -7.2 1.7 -5.5 0.0
## link
## 1 /players/a/abrinal01.html
## 2 /players/a/acyqu01.html
## 3 /players/a/adamsst01.html
## 4 /players/a/adebaba01.html
## 5 /players/a/afflaar01.html
## 6 /players/a/aldrico01.html
Look at selector gadget for a team’s website, e.g. Denver Nuggets. Suppose you want to find everybody who played for the Nuggets last year, and then their stats. Remember to use Chrome (ugh).
library(rvest)
## Loading required package: xml2
url <- "http://www.basketball-reference.com/teams/DEN/2017.html"
links <- xml2::read_html(url) %>%
rvest::html_nodes(".center+ .left a") %>%
rvest::html_attr('href')
links
## [1] "/players/a/arthuda01.html" "/players/b/bartowi01.html"
## [3] "/players/b/beaslma01.html" "/players/c/chandwi01.html"
## [5] "/players/f/farieke01.html" "/players/g/gallida01.html"
## [7] "/players/g/geeal01.html" "/players/h/harriga01.html"
## [9] "/players/h/hernaju01.html" "/players/h/hibbero01.html"
## [11] "/players/j/jokicni01.html" "/players/m/millemi01.html"
## [13] "/players/m/mudiaem01.html" "/players/m/murraja01.html"
## [15] "/players/n/nelsoja01.html" "/players/n/nurkiju01.html"
## [17] "/players/o/obryajo01.html" "/players/p/plumlma01.html"
## [19] "/players/s/stokeja01.html"