The code in this document generates an interactive scatter plot using the Plotly library. The plot compares the offensive performance of selected players from the 2020 NBA Draft’s first round in the 2022-23 season. The x-axis represents Field Goal Percentage (FG%), showing the accuracy of field goal attempts in tenths of a percentage point (20.00%, 30.00%, etc.), while the y-axis represents Points Per Game (PPG). Each player is represented as a marker on the plot. Hovering over a marker displays information about the player’s name, FG%, and PPG. The plot helps analyze the relationship between shooting efficiency and scoring volume for these players.
# Fetch the web page content
url <- "https://www.basketball-reference.com/leagues/NBA_2023_per_game.html"
page <- read_html(url)
# Extract data from the web page
players_data <- page %>%
html_table(fill = TRUE) %>%
`[[`(1) %>%
as.data.frame()
# Select the required players
selected_players <- c('LaMelo Ball', 'Anthony Edwards', 'James Wiseman', 'Patrick Williams', 'Isaac Okoro',
'Onyeka Okongwu', 'Killian Hayes', 'Obi Toppin', 'Deni Avdija', 'Jalen Smith',
'Devin Vassell', 'Tyrese Haliburton', 'Kira Lewis Jr.', 'Aaron Nesmith', 'Cole Anthony', 'Isaiah Stewart',
'Aleksej Pokusevski', 'Josh Green', 'Saddiq Bey', 'Precious Achiuwa', 'Tyrese Maxey', 'Zeke Nnaji', 'Leandro Bolmaro',
'RJ Hampton', 'Immanuel Quickley', 'Payton Pritchard', 'Udoka Azubuike', 'Jaden McDaniels', 'Malachi Flynn', 'Desmond Bane')
# Filter data for selected players
selected_players_data <- players_data %>%
filter(Player %in% selected_players)
# Convert columns to numeric data types
numeric_cols <- c('Age', 'G', 'GS', 'MP', 'FG', 'FGA', 'FG%', '3P', '3PA', '3P%', '2P', '2PA', '2P%', 'FT',
'FTA', 'FT%', 'ORB', 'DRB', 'TRB', 'AST', 'STL', 'BLK', 'TOV', 'PF', 'PTS')
selected_players_data[numeric_cols] <- lapply(selected_players_data[numeric_cols], as.numeric)
# Manually remove specific rows
rows_to_remove <- c(8, 9, 32, 33)
selected_players_data <- selected_players_data[-rows_to_remove, ]
# Display the data frame
print(selected_players_data)
## Rk Player Pos Age Tm G GS MP FG FGA FG% 3P 3PA 3P%
## 1 1 Precious Achiuwa C 23 TOR 55 12 20.7 3.6 7.3 0.485 0.5 2.0 0.269
## 2 13 Cole Anthony PG 22 ORL 60 4 25.9 4.6 10.2 0.454 1.3 3.4 0.364
## 3 16 Deni Avdija SF 22 WAS 76 40 26.6 3.3 7.6 0.437 0.9 3.1 0.297
## 4 18 Udoka Azubuike C 23 UTA 36 4 10.0 1.6 2.0 0.819 0.0 0.0 NA
## 5 21 LaMelo Ball PG 21 CHO 36 36 35.2 8.2 20.0 0.411 4.0 10.6 0.376
## 6 24 Desmond Bane SG 24 MEM 58 58 31.7 7.8 16.2 0.479 2.9 7.0 0.408
## 7 40 Saddiq Bey SF 23 TOT 77 37 27.6 4.6 10.9 0.422 2.0 5.4 0.361
## 10 48 Leandro Bolmaro SF 22 UTA 14 0 4.9 0.2 1.4 0.150 0.0 0.3 0.000
## 11 140 Anthony Edwards SG 21 MIN 79 79 36.0 8.9 19.5 0.459 2.7 7.3 0.369
## 12 147 Malachi Flynn PG 24 TOR 53 2 13.0 1.6 4.6 0.360 0.9 2.5 0.353
## 13 181 Josh Green SG 22 DAL 60 21 25.7 3.4 6.4 0.537 1.1 2.8 0.402
## 14 186 Tyrese Haliburton PG 22 IND 56 56 33.6 7.4 15.0 0.490 2.9 7.2 0.400
## 15 204 Killian Hayes PG 21 DET 76 56 28.3 4.0 10.7 0.377 1.1 3.8 0.280
## 16 291 Kira Lewis Jr. PG 21 NOP 25 0 9.4 1.6 3.5 0.455 0.6 1.4 0.441
## 17 316 Tyrese Maxey SG 22 PHI 60 41 33.6 7.3 15.2 0.481 2.7 6.2 0.434
## 18 322 Jaden McDaniels SF 22 MIN 79 79 30.6 4.7 9.1 0.517 1.4 3.4 0.398
## 19 358 Aaron Nesmith SF 23 IND 73 60 24.9 3.5 8.1 0.427 1.6 4.3 0.366
## 20 362 Zeke Nnaji PF 22 DEN 53 5 13.7 2.1 3.7 0.561 0.3 1.2 0.262
## 21 372 Onyeka Okongwu C 22 ATL 80 18 23.1 4.0 6.2 0.638 0.1 0.2 0.308
## 22 373 Isaac Okoro SF 22 CLE 76 46 21.7 2.3 4.7 0.494 0.8 2.3 0.363
## 23 387 Aleksej Pokusevski PF 21 OKC 34 25 20.6 3.2 7.3 0.434 1.1 3.1 0.365
## 24 400 Payton Pritchard PG 25 BOS 48 3 13.4 2.1 5.1 0.412 1.2 3.2 0.364
## 25 403 Immanuel Quickley SG 23 NYK 81 21 28.9 5.2 11.6 0.448 2.1 5.6 0.370
## 26 454 Jalen Smith C 22 IND 68 31 18.8 3.6 7.5 0.476 0.8 2.8 0.283
## 27 459 Isaiah Stewart C 21 DET 50 47 28.3 3.9 8.8 0.442 1.3 4.1 0.327
## 28 476 Obi Toppin PF 24 NYK 67 5 15.7 2.8 6.3 0.446 1.3 3.7 0.344
## 29 486 Devin Vassell SG 22 SAS 38 32 31.0 6.9 15.7 0.439 2.7 7.0 0.387
## 30 523 Patrick Williams PF 21 CHI 82 65 28.3 3.8 8.3 0.464 1.4 3.4 0.415
## 31 530 James Wiseman C 21 TOT 45 22 19.3 4.2 7.5 0.558 0.1 0.4 0.200
## 2P 2PA 2P% eFG% FT FTA FT% ORB DRB TRB AST STL BLK TOV PF PTS
## 1 3.0 5.4 0.564 .521 1.6 2.3 0.702 1.8 4.1 6.0 0.9 0.6 0.5 1.1 1.9 9.2
## 2 3.4 6.7 0.500 .516 2.5 2.8 0.894 0.8 4.0 4.8 3.9 0.6 0.5 1.5 2.6 13.0
## 3 2.4 4.6 0.530 .497 1.6 2.2 0.739 1.0 5.4 6.4 2.8 0.9 0.4 1.6 2.8 9.2
## 4 1.6 2.0 0.819 .819 0.2 0.6 0.350 0.9 2.4 3.3 0.3 0.2 0.4 0.5 0.9 3.5
## 5 4.2 9.4 0.450 .510 2.8 3.4 0.836 1.2 5.3 6.4 8.4 1.3 0.3 3.6 3.3 23.3
## 6 4.9 9.2 0.534 .568 3.1 3.5 0.883 0.7 4.3 5.0 4.4 1.0 0.4 2.2 2.6 21.5
## 7 2.6 5.4 0.483 .513 2.7 3.1 0.861 1.3 3.4 4.7 1.5 0.9 0.2 0.9 1.6 13.8
## 10 0.2 1.1 0.188 .150 0.0 0.0 NA 0.3 0.2 0.5 0.5 0.2 0.1 0.5 0.7 0.4
## 11 6.3 12.2 0.513 .528 4.0 5.3 0.756 0.6 5.2 5.8 4.4 1.6 0.7 3.3 2.4 24.6
## 12 0.8 2.1 0.367 .457 0.5 0.6 0.758 0.3 1.2 1.4 1.3 0.4 0.1 0.5 1.2 4.6
## 13 2.3 3.6 0.643 .626 1.1 1.6 0.723 0.9 2.1 3.0 1.7 0.7 0.1 1.2 2.6 9.1
## 14 4.5 7.8 0.572 .586 3.1 3.6 0.871 0.6 3.1 3.7 10.4 1.6 0.4 2.5 1.2 20.7
## 15 3.0 7.0 0.429 .426 1.2 1.5 0.821 0.4 2.5 2.9 6.2 1.4 0.4 2.3 2.9 10.3
## 16 1.0 2.2 0.463 .540 0.8 0.9 0.864 0.2 1.1 1.3 0.9 0.4 0.1 0.4 1.0 4.6
## 17 4.7 9.1 0.513 .568 3.0 3.6 0.845 0.4 2.6 2.9 3.5 0.8 0.1 1.3 2.2 20.3
## 18 3.3 5.7 0.588 .591 1.3 1.8 0.736 1.2 2.7 3.9 1.9 0.9 1.0 1.4 3.4 12.1
## 19 1.9 3.8 0.496 .525 1.6 1.9 0.838 0.8 2.9 3.8 1.3 0.8 0.5 1.0 3.2 10.1
## 20 1.8 2.5 0.710 .605 0.8 1.2 0.645 1.2 1.4 2.6 0.3 0.3 0.4 0.6 2.0 5.2
## 21 3.9 6.1 0.647 .642 1.9 2.5 0.781 2.7 4.5 7.2 1.0 0.7 1.3 1.0 3.1 9.9
## 22 1.5 2.4 0.617 .582 1.0 1.4 0.757 0.7 1.8 2.5 1.1 0.7 0.4 0.6 2.1 6.4
## 23 2.1 4.3 0.483 .510 0.6 1.0 0.629 1.3 3.4 4.7 1.9 0.6 1.3 1.3 1.7 8.1
## 24 0.9 1.9 0.495 .527 0.3 0.3 0.750 0.5 1.3 1.8 1.3 0.3 0.0 0.8 0.8 5.6
## 25 3.1 6.0 0.521 .537 2.5 3.1 0.819 0.7 3.4 4.2 3.4 1.0 0.2 1.2 2.0 14.9
## 26 2.8 4.7 0.593 .530 1.5 2.0 0.759 1.9 3.9 5.8 1.0 0.3 0.9 1.1 2.3 9.4
## 27 2.6 4.7 0.542 .518 2.2 3.0 0.738 2.3 5.8 8.1 1.4 0.4 0.7 1.4 2.7 11.3
## 28 1.5 2.6 0.593 .548 0.6 0.7 0.809 0.4 2.4 2.8 1.0 0.3 0.2 0.6 1.0 7.4
## 29 4.2 8.7 0.480 .525 2.1 2.6 0.780 0.2 3.7 3.9 3.6 1.1 0.4 1.5 1.5 18.5
## 30 2.4 4.9 0.498 .549 1.1 1.3 0.857 1.0 3.0 4.0 1.2 0.9 0.9 1.2 1.8 10.2
## 31 4.1 7.1 0.580 .563 1.5 2.2 0.701 1.6 4.3 5.9 0.7 0.2 0.6 1.1 2.4 10.0
Below, you will find the code for an interactive scatter plot for the first round of the 2020 NBA Draft class from the 2022-23 season.
# Create a named vector of colors for each player
player_colors <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#FFFF00", "#9467bd",
"#8c564b", "#e377c2", "#7f7f7f", "#40826D", "lightgreen", "#E52B50",
"red4", "purple4", "#FF2400", "darkgreen", "skyblue", "darkblue", "turquoise",
"tan", "gold4", "#AD6F69", "#6495ED", "#007FFF", "cyan", "#563C5C", "#00B7EB", "#7FFF00",
"#BEBEBE", "#87421F", "#FA8072")
# Map colors to players
selected_players_data$Color <- player_colors[match(selected_players_data$Player, selected_players)]
# Define a custom tick formatting function for formatting x axis percentages appropriately
custom_tick_format <- function(x) {
paste0(sprintf("%.2f", x * 100), "%")
}
# Create the scatter plot using Plotly
scatter_plot <- plot_ly(data = selected_players_data, x = ~`FG%`, y = ~PTS,
text = ~paste("Player: ", Player, "<br>FG%: ", `FG%`, "<br>Points Per Game: ", PTS),
type = 'scatter', name = "ON/OFF", mode = 'markers',
marker = list(size = 12, opacity = 0.8, color = ~Color)) %>%
layout(
title = " Scatter Plot: Field Goal % vs. Points Per Game Comparison (2022-23)",
xaxis = list(
title = "Field Goal Percentage",
tickvals = seq(0.2, 0.8, 0.1),
ticktext = lapply(seq(0.2, 0.8, 0.1), custom_tick_format)
),
yaxis = list(title = "Points Per Game"),
legend = list(orientation = "h", x = 0.1, y = -0.1),
annotations = list(
list(text = "<i>2020 NBA Draft Class (1st Round)</i>",
showarrow = FALSE,
xref = "paper",
yref = "paper",
x = 0.5,
y = 1.021, # Adjust the y value to position the annotation closer to the title
font = list(size = 12, color = "black"))
),
hoverlabel = list(bgcolor = "white", font = list(family = "Arial", size = 12, color = "black")),
plot_bgcolor = "rgba(240, 240, 240, 0.7)",
paper_bgcolor = "rgba(255, 255, 255, 0.9)",
hovermode = "closest",
showlegend = TRUE
) %>%
config(displayModeBar = FALSE) # Hide the display mode bar
# Display the interactive scatter plot
scatter_plot
The goal of this plot is to show a few points:
Efficiency vs. Scoring: FG% vs. PPG helps understand the trade-off between shooting efficiency and scoring volume. Players with a high FG% might not score as many points if they take fewer shots, while players with a high PPG might have a lower FG% if they take many attempts.
Shooting Consistency: Players who maintain a high FG% while contributing a significant number of points indicates consistent and effective shot selection.
Offensive Skill: The plot shows how often a player converts their field goal attempts into points. Players with both a high FG% and PPG demonstrate strong offensive skill.
Playing Style: Some players might have a high PPG due to their ability to make difficult shots, while others excel in high-percentage shots.
Role Players vs. Stars: The plot helps differentiate between role players (high FG%, lower PPG) and star players (high PPG, respectable FG%) within a team.
Efficient Scorers: Players in the upper-mid quadrant (high FG% and high PPG) are efficient scorers who make a significant offensive impact.
Team Strategy: The plot can offer insights into a team’s offensive strategy, such as relying on efficient scorers or volume shooters.