LeBron James: Creating Three-Point Shots

Ben Howell
Texas Sports Analytics Group
6 min readFeb 4, 2021

--

LeBron James is one of the best passers in the NBA right now, despite being a nominal “Small Forward”. As he led the Los Angeles Lakers to the 2019–2020 NBA title, James set a career-high in assists per game (APG), dishing out a league-leading 10.2 APG. While the Lakers themselves aren’t a huge 3-point shooting team, only making 35% of the 31.6 three-pointers that they took in the 19–20 season, 763 of those were catch-and-shoot threes from a LeBron pass.

This tracking data from PBP Stats has graciously been made available by Darryl Blackport on his GitHub. I’m going to take you through the data, show you how to manipulate it, and how to create some cool visualizations using R and RStudio. The code for this piece can be found here.

The dataset contains data on all catch-and-shoot 3-point attempts off of a LeBron pass from the 2019–2020 season.

Step one of any analysis in R is loading packages. For this process, we’re using the tidyverse and kableExtra packages. These packages will allow us to put together visualizations; if we were interested in modeling something, like the chance of making a certain shot, we’d load in some of these other packages.

#if you're starting from scratch, you can load these packages in with 'install.packages(PACKAGE)'#loading packages
library(tidyverse)
library(mgcv)
library(kableExtra)
library(nbastatR)

Next, we want to load in the data. Since the data is readily available on Darryl’s GitHub page, we can just pull the data from there. I’ve also created a few other variables.

  • pct: a dummy variable so we can show the % of shots that went in at a certain location
  • pass_x and pass_y: changing a factor to a numeric variable so we can graph it
  • where: which side of the court a shot was taken on

What follows here is the process of putting together a rendering of a basketball court. While we could view the data without the underlying court, it would be more difficult to interpret, especially when we look at the pass locations, which come from everywhere on the court. With the shots taken, we see a pretty clear pattern emerge in where the three-point line should be. What we’ve done is passed this to a new function, called court, which is hosted in our environment so we can use it whenever we need to.

in_x <- c(-75, -75, 75, 75)
in_y <- c(-35, 150, 150, -35)inner <- data.frame(in_x, in_y)court <- function(...) {
ggplot(...) +
geom_segment(aes(x = -215, xend = -215, y = -35, yend = 100)) +
geom_segment(aes(x = 215, xend = 215, y = -35, yend = 100)) +
geom_curve(aes(x = -215, xend = 215,
y = 100, yend = 100), curvature = -0.66) +
geom_path(data = inner, aes(x = in_x, y = in_y)) +
geom_curve(aes(x = -65, xend = 65,
y = 150, yend = 150),
curvature = 1, linetype = "dashed") +
geom_curve(aes(x = -65, xend = 65,
y = 150, yend = 150),
curvature = -1) +
theme_bw() +
theme(panel.grid.minor = element_blank())
}

Now we’re ready to start diving into our data.

Here’s a simple scatterplot of all the catch-and-shoot three-pointers that LeBron has initiated.

That’s a lot of shots! But we can’t really see any patterns in what kinds of shots go in. However, I wasn’t really expecting to find any pattern from the shot locations; this data is for a variety of Laker of players from the past season, so each comes with their own tendencies and three-point FG%.

shots %>%
court +
geom_point(aes(x = x, y = y, color = made)) +
labs(x = "Baseline", y = "Sideline",
title = "Shots off of LeBron Passes from 2019-2020") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"))
Shots locations off of a LeBron James pass from 2019–2020

But what about the locations from which LeBron is passing to these threes?

Here we’re using a heatmap to indicate which locations LeBron passed the most from. I’ve also broken it down by whether the shot was made (True = Make, False = Miss), and a general idea of where the shot was (Corner3 or Arc3). Both of these variables were a part of the original dataset, though we are using the pass_x and pass_y variables that we created earlier for where the pass originated from.

Heatmap for LeBron James passes, broken down by shot location and result

Now we’re getting somewhere, with a pattern starting to appear in the location of LeBron’s passes to certain types of shots. When he passes into a corner three, the pass is usually coming from the paint, likely as LeBron is posted up and surveying the offense and defense around him.

Arc 3s have a different pattern, with most of the passes into Arc 3s coming closer to the three-point line. We also see that his successful passes come typically at the elbows, while passes from the top of the key are less successful. There are a myriad of reasons why this may occur, whether it’s who is taking Arc 3s versus Corner 3s, the angle at which they receive the pass based on LeBron’s position, or factors outside their control, such as the defense’s positioning.

We see here that the Lakers’ players shot significantly better on Corner3 attempts than Arc3 attempts from LeBron, which is to be expected. Shots from the corner usually have a higher FG% than arc shots, partially due to being closer to the basket and having a better line of sight.

Breakdown of 3-point shooting% by location

That’s great, but saying that corner threes are better than arc threes is not an earth-shattering realization. What can help an opponent game plan for the Lakers is knowing which players are dangerous three-point shooters from the corner, the arc, or not at all.

Breakdown of three-point shooting% by player and location

On 40 corner threes off of a LeBron pass, Kyle Kuzma shot 60% from deep, a huge step forward over his career average 3-pt% of 33.3%. We also see a much lower 31% 3-pt% on Arc3s, which gives us an actionable plan. If you’re facing the Lakers with LeBron in the post, you want to force Kyle Kuzma up on the wing, so that he doesn’t get easy corner three attempts. We can see this difference represented below on the heatmap of Kuzma’s shots; there’s more concentrated red in the corners while blue is much more prevalent on the wings.

Kyle Kuzma shots and average 3P% by location on LeBron passes

Forcing Kuzma onto the wings wouldn’t be a winning strategy if that gave him the opportunity to drive to the basket, but that isn’t a strength of Kuzma’s. Throughout his career, Kuzma is averaging just 2.8 free-throw attempts per game; he’s been most effective for LeBron as a spot-up shooter, so teams should force him out of the corner to limit the damage that he may do.

(Obviously, if you’re game-planning for the Lakers, you’re focused more on LeBron and Anthony Davis, but Kuzma made a good example here due to his Corner3 and Arc3 splits.)

This is a simple look at working with an visualizing NBA shot-tracking data. Later this week, I’ll have another piece up, using the same dataset, on creating an expected 3-pt FG%. Stay tuned, and you can find this dataset here if you want to play with it yourself.

--

--

Ben Howell
Texas Sports Analytics Group

Sophomore studying Sport Management and Economics at the University of Texas. Writing about Baseball from an analytical and scouting perspective