In my last post I produced some NBA shot charts in R using data scraped from stats.nba.com and ggplot2
. This time I extracted all shot location data available for 490 players and linked it to a Tableau dashboard.
The first dashboard shows each shot attempted during the 2014-15 NBA Regular Season. On the right, it is possible to select team, player, shot type, shot zone and shot range. The table above the chart is also updated in line with the filter selection (click on the image to open the dashboard on a new window).
Another way to visualise this data is to group shots by shot zone. The dashboard below displays shot accuracy for each zone of the court. Note how the “Above the Break 3” area is located in the 2-point region. This is due to the fact that I averaged the X and Y coordinates of all shots taken from “Above the Break 3”. Shots taken from the left and right bring the average location inside the 2-point region.
The half court image is the same I used in my last post. This is how you we add the image to the plot:
Map -> Background Image -> Add Image…
Select the NBA court jpeg file and click Edit. The X field limits should be -250 to 250 and Y field limits should be -52 to 418.
In order to scrape and save the shot data using R, I created a function that extract data for a player and ran it in a loop. This will take some time to run depending on the memory you have available (when I first ran this code it took about 40 minutes). Once we have the data in a readable format it is time to link it to Tableau.
## load the file players.csv from my NBA Shot Chart project repo in my GitHub page. players <- read.csv("players.csv", header = TRUE) ## create function library(rjson) AllShotData <- function(playerID) { # Shot Data shotURL <- paste("http://stats.nba.com/stats/shotchartdetail?CFID=33&CFPARAMS=2014-15&ContextFilter=&ContextMeasure=FGA&DateFrom=&DateTo=&GameID=&GameSegment=&LastNGames=0&LeagueID=00&Location=&MeasureType=Base&Month=0&OpponentTeamID=0&Outcome=&PaceAdjust=N&PerMode=PerGame&Period=0&PlayerID=",playerID,"&PlusMinus=N&Position=&Rank=N&RookieYear=&Season=2014-15&SeasonSegment=&SeasonType=Regular+Season&TeamID=0&VsConference=&VsDivision=&mode=Advanced&showDetails=0&showShots=1&showZones=0", sep = "") # import from JSON shotData <- fromJSON(file = shotURL, method="C") # unlist shot data, save into a data frame shots <- data.frame(matrix(unlist(shotData$resultSets[[1]][[3]]), ncol=21, byrow = TRUE)) # shot data headers colnames(shots) <- shotData$resultSets[[1]][[2]] # covert x and y coordinates into numeric shots$LOC_X <- as.numeric(as.character(shots$LOC_X)) shots$LOC_Y <- as.numeric(as.character(shots$LOC_Y)) shotsSHOT_DISTANCE <- as.numeric(as.character(shots$SHOT_DISTANCE)) # return table return(shots) } ## Execute shot data function in loop shots.output <- data.frame() for (i in players$player_id) { tryCatch({ shots.output <- rbind(shots.output, AllShotData(i)); }, error=function(e){cat("ERROR in series", i,":", conditionMessage(e), "\n") }) } # View and save shot data View(shots.output) save(shots.output, file = "Shot Location Data.RData")
Feel free to comment or ask any questions in the comment section below.
It says:
Error: Object ‘players’ not found
LikeLike
Go to the NBA shot chart project repo on my GitHub page and download the file players.csv
Load the file into R and save it into a data frame object called
players
.Re run the code and it should work.
LikeLike
I’ve downloaded the file from GitHub but I’m unsure how to load in a csv file. Could you help me out?
Thank you
LikeLike
If you are talking about players.csv file, read my other comment. If you are talking about the .R file, you can load it using Rstudio and run it.
LikeLike
Where do I put the ‘players.csv’ file once I download it?
LikeLike
This file is a list of all players and playerIDs with existing shot data and can be used as a reference for player id’s. If you want to run charts for Kevin Durant for example, search for his name on the file and you will find the id 201142.
LikeLike
This is really awesome! How were you able to figure out the URL for the JSON?
LikeLike
I followed these steps from Greg Reda’s post. You basically need to start the developer tools in Chrome and go to the page that has the data you are looking for.
LikeLike
Does this still work? Or has NBA.com masked data?
LikeLike
It should work still. NBA may have changed the tables structure since then.
I am working on player performance data for each game (game logs) and using the following code:
library(jsonlite)
library(RCurl)
#### Player game logs URL: one record per player per game played ####
gameLogsURL <- paste("http://stats.nba.com/stats/leaguegamelog?Counter=1000&Direction=DESC&LeagueID=00&PlayerOrTeam=P&Season=2016-17&SeasonType=Regular+Season&Sorter=PTS")
#### Import game logs data from JSON ####
# use jsonlite::fromJSON to handle NULL values
gameLogsData <- jsonlite::fromJSON(gameLogsURL, simplifyDataFrame = TRUE)
# Save into a data frame and add column names
gameLogs <- data.frame(gameLogsData$resultSets$rowSet)
colnames(gameLogs) <- gameLogsData$resultSets$headers[[1]]
It works fine.
LikeLike