Resumen


Este estudio busca aplicar la clasificación no supervisada para agrupar a los jugadores de la National Basketball Association (NBA) basado en su desempeño en la cancha y estilo de juego, o sea ir más allá de las posiciones tradicionales. Usaremos una base de datos que contiene las estadísticas de los jugadores en la temporada reciente para varias de las cosas que se hacen dentro del juego. Luego intentamos captar las características de cada grupo al analizar y comparar cada uno contra cada variable. Finalmente, analizamos si la producción y estilo afecta el salario del jugador.

Introducción


Todo en la vida evoluciona con el tiempo. La liga de baloncesto más prestigiosa del mundo, la NBA en Estados Unidos, no es excepción. A cada rato se introducen o modifican las reglas del juego. Se cambia la estructura de la competencia; por ejemplo cuando se han añadido nuevas franquicias o cuando ajustan detalles como fechas y topes salariales. Incluso, la aparición y el crecimiento de las redes sociales y las apuestas deportivas han ido creando nuevas formas de hacer negocio.

Ahora, la liga no sería posible sin la dedicación y el talento atlético extraordinario de los jugadores. Eso nos lleva al punto de este estudio. Los jugadores son otro aspecto que ha evolucionado. Miremos específicamente sus destrezas y estilos de jugar. En un juego de hoy día, vemos jugadores más pequeños en altura atrapando diez rebotes, los jugadores más altos manejando el balón, y a jugadores que su especialidad es lanzar del área de tres puntos y defender. A diferencia de épocas anteriores donde cada uno de los cinco jugadores en cancha tenía una posición y un rol específico, típicamente basados en su altura y bastante estándar entre todos los equipos.

Entender la evolución en las destrezas de los jugadores puede ser vital para la calidad del producto que venden los equipos de la NBA, es decir sus juegos de baloncesto. Primero para los dirigentes, encargados de crear alineaciones y estrategias para su equipo, ¿qué jugadores pueden poner a jugar juntos porque sus destrezas varían o se complementan? Por ejemplo, un equipo competitivo no puede tener en cancha solamente cinco jugadores que prefieren producir en la zona de la pintura, porque te limitas a anotar desde esa área nada más. Segundo, para los general managers, encargados de armar el plantel, ¿qué jugador debería intentar atraer al equipo porque con sus destrezas sería un buen fit y cuánto dinero sería justo ofrecerle basado en su producción? Un equipo competitivo debe evitar situaciones donde la producción de un jugador no valga todo lo que se le paga, o donde pierden un buen talento jovén por no pagarle lo suficiente. Técnicas de minería de datos pudieran ser útiles para analizar a los jugadores y facilitar la toma de decisiones como estas.

Revisión de Literatura


Al analizar la literatura sobre cómo ha evolucionado el juego del baloncesto en la NBA, encontramos varios cambios obvios como el ritmo del juego, la rudeza en la pintura, la diversidad de estilos y el surgimiento del tiro de 3 puntos.

En las primeras décadas, el baloncesto se caracterizaba por un juego estático y pausado, con pases y cortes en la zona, y pocos tiros desde afuera. Con el tiempo, el juego se fue acelerando y favoreciendo las transiciones rápidas, los contragolpes y los tiros rápidos. Esto se debió en parte a la introducción del reloj de posesión en 1954, que limitaba el tiempo que un equipo podía tener el balón sin tirar a canasta (Competize, 2023). También influyó el aumento de la capacidad física y atlética de los jugadores, que podían correr más y saltar más alto (NBA, 2022).

Antes el juego interior era más físico y agresivo, con faltas duras y contactos constantes. Esto se debía a que había más centros dominantes y a que se permitía más contacto por parte de los árbitros (NBA, 2022). Con las normativas actuales, se ha suprimido el exceso de fuerza y se sanciona más severamente las faltas antideportivas o intencionadas (NBA, 2022). Además, muchos centros han ampliado su rango de tiro y han salido más al perímetro, lo que ha reducido el juego en la zona (Competize, 2023).

Antes había una mayor homogeneidad en la forma de jugar de los equipos, basada en el juego colectivo y el dominio de los centros. Los equipos seguían patrones similares de ataque y defensa, sin mucha variedad ni creatividad (Facundo, 2022). Ahora hay más diversidad e innovación en las estrategias y los roles de los jugadores, con mayor protagonismo de los bases y los aleros. Los equipos se adaptan a las características de sus jugadores y buscan explotar sus fortalezas o las debilidades del rival (Facundo, 2022). Por ejemplo, ahora la capacidad de cambiar defensores en las pantallas es una habilidad muy valorada en la NBA moderna. Esto ha llevado a una disminución en el uso de los centros tradicionales y un cambio hacia alineaciones más versátiles que pueden evitar desajustes potenciales.

Finalmente, a pesar de los cambios anteriormente mencionados, tal vez el más importante ha sido el uso del tiro de tres puntos. El tiro de tres puntos fue introducido en la NBA en la temporada 1979-1980, pero no se usó mucho hasta los años 90. Antes se prefería penetrar a canasta o tirar desde media distancia, ya que se consideraba más seguro y eficaz (Competize, 2023). Con el tiempo, se fue incrementando el uso y la eficiencia del tiro de tres puntos, especialmente después del éxito de los Warriors con sus tiradores Curry y Thompson, que rompieron varios récords de triples anotados (Competize, 2023). Ahora muchos equipos basan su ofensiva en el tiro exterior, buscando espaciar la cancha y generar ventajas (Competize, 2023). Interesantemente, los jugadores no están disparando con un porcentaje mucho mayor que hace 20 o 30 años, pero sí están disparando más (Fenichel, 2022). Eso sí, los jugadores de gran tamaño han mejorado notablemente en el tiro de 3 puntos.


Metodología


El método especifico de clasificación no supervisada que utilizaremos es el clúster jerárquico. Sombreado en gris mostramos todos los códigos corridos en RStudio. Antes y después de los cuadros sombreados, brindamos comentarios acerca de los pasos del proceso y las salidas.

Llamar paqueterías necesarias

library(tidyverse)
library(plotly)
library(factoextra)
library(dendextend)
library(visdat)
library(mice)

Lectura de archivo

# Los datos fueron extraídos de la fuente a un archivo Excel y guardado localmente como "Complete.csv"
# Se fijó el directorio de trabajo.
### setwd("/Users/miguel.torres/Desktop/ESTA 5504/R/Bases de Datos/Proyecto Final NBA")

Original <- read.csv("Complete.csv",row.names=1)

Original


Descripción de los Datos


Nuestra base de datos original cuenta con 539 filas. Cada fila contiene un jugador que estuvo activo en por lo menos un (1) partido de la temporada regular 2022-2023 de la NBA, disputada entre octubre 2022 y abril 2023.

Nuestra base de datos cuenta con 34 columnas. Las primeras dos columnas son del pérfil del jugador, y el resto son diferentes métricas sobre su desempeño en la cancha. Estas variables las seleccionamos manualmente entre las distintas secciones que tiene la fuente porque creíamos que eran las más fáciles de entender aún para los que no sean seguidores del baloncesto y las que mejor pueden distinguir a los jugadores.

Diccionario de Variables


Puede acceder al siguiente enlace para más información acerca de la fuente de los datos y detalles sobre cada una de las variables:

https://rpubs.com/miguel_torres/1043620

Limpieza de Datos

La base de datos requiere de varios procesos de limpieza antes de proceder a nuestro análisis estadístico:

Filas y Columnas

Todas las siguientes columnas representan porcientos, pero aparecen en números enteros. Las transformamos a decimales para interpretarlas de manera más fácil.

Original$FG. <- Original$FG./100
Original$FT. <- Original$FT./100
Original$X.FGA_2PT <- Original$X.FGA_2PT/100
Original$X.FGA_3PT <- Original$X.FGA_3PT/100
Original$X.PTS_2PT_PITP <- Original$X.PTS_2PT_PITP/100
Original$X.PTS_2PT_MR <- Original$X.PTS_2PT_MR/100
Original$X.PTS_3PT <- Original$X.PTS_3PT/100
Original$X.PTS_FT <- Original$X.PTS_FT/100
Original$CAS_FREQ <- Original$CAS_FREQ/100
Original$PULLUP_FREQ <- Original$PULLUP_FREQ/100


Próximo, las estadísticas de jugadores que jugaron una cantidad limitada de juegos puede que no provean una buena representación de sus verdaderas habilidades y capacidad de producción. Los que jugaron una cantidad limitada de minutos por juego puede que su producción sea demasiado inconsistente y sus estadísticas tampoco sean representativas. Para que el clustering encuentre patrones confiables, hay que encontrar un corte balanceado de manera que no incluyamos estos jugadores pero no excluyamos jugadores que aportan significativamente a los patrones.

Data <- Original %>% filter(GP>=30 & MIN >=10)

Siguiendo el teorema central del límite, decidimos dejar aquellos jugadores que estuvieron activos en al menos 30 partidos. Ya que entendemos que aquellos que tengan menos iban a generar ruido y que era perjudicial para la clasificación.


Podemos observar en este gráfico estandarizado que a mayor minutos, mayor es la variabilidad de los datos. Lo cual es saludable a la hora de clasificar los grupos. Sin embargo esto viene con un problema…

A continuación, en estas 2 gráficas podemos observar el comportamiento de las observaciones. Tanto en un gráfico de densidad como en uno de scatterplots. Es un trade-off entre minutos jugados e información perdida o ganada. Donde obtuvimos una mayor ganancia marginal en minutos = 10.


Luego de aplicar el filtro nos quedamos con 383 jugadores para el proceso de clustering.

Datos Faltantes

vis_miss(Data)

Data <- replace(Data,is.na(Data),0)    
vis_miss(Data)


Nos dimos cuenta que sí habían datos faltantes (NAs) para algunos jugadores. Estos estaban en las columnas de frecuencia de tiros “catch-and-shoot” y “pull-up”. Sin embargo, NA en estos casos significa que el jugador nunca lanzó un intento de esos estilos en toda la temporada. Por tanto, es apropiado proceder a reeemplazar los NAs con 0.

Reescalado de Valores

Finalmente, un paso importante para poder hacer el proceso de clustering es normalizar todas las variables númericas, para que las variables con mediciones distintas no generen ruido. En este caso, se estandarizarán con valores z.

data.scaled <- as.data.frame(scale(x = Data[,-1],
                     center = TRUE,
                     scale = TRUE))
head(data.scaled)


Clustering

Decidir k-Óptimo

fviz_nbclust(data.scaled, FUN = hcut, method = "silhouette")

fviz_nbclust(data.scaled, FUN = hcut, method = "wss")

fviz_nbclust(data.scaled, FUN = hcut, method = "gap_stat")


Tanto los métodos de silueta (silhouette) como de codo (wss) nos dijeron que k = 3 es el número óptimo de grupos. El método de gap (gap_stat) nos dijo que k = 9 es el número óptimo de grupos. Dejándonos llevar por el objetivo de la investigación de agrupar a los jugadores basado en su desempeño y estilo de juego, escogeremos k = 9 como el k-óptimo. Sentimos que con 3 grupos, los grupos no serán tan elaborados. Es decir, lo más que lograremos captar es que los jugadores de un grupo son “los mejores”, los del otro “buenos” y los del último “regulares”.

Modelo

Corremos entonces un módelo jerárquico. Utilizamos la distancia euclidiana y el método de valores máximos (o complete). Visualizamos este modelo mediante un dendrograma dividido en 9 grupos.

dist      <- dist(data.scaled,method = "euclidean")


modelo2 <- hclust(dist, method = "complete")




dendrograma <- fviz_dend(modelo2, cex = 0.5, k=9, 
          rect = TRUE,  
          k_colors = "jco",
          rect_border = "jco", 
          rect_fill = TRUE,
          ggtheme = theme_bw())


ggplotly(dendrograma)


Corremos la función que le asigna un número a cada grupo que generó el módelo jerárquico. Vemos la distribución; es decir cuantos jugadores hay en cada grupo. Luego incorporamos el número de grupo del jugador a sus datos. Así podremos generar observaciones acerca de las características de cada grupo; es decir, porque se agruparon los jugadores de tal manera.

grupos <- cutree(modelo2, k=9) 
table(grupos)
## grupos
##   1   2   3   4   5   6   7   8   9 
##   5  31  17  79  12  10 169  12  48
Data$grupo <- grupos

Discusión de Resultados


Podemos visualizar y explorar los valores que tienen cada grupo para cada variable mediante boxplots. Esto nos ayudará a describir y nombrar a cada grupo basado en las características que logremos captar y compararlos.

variable_list <- c("PTS","FGM","FGA","FG.","X3PM","X3PA","FTM","FTA","FT.","OREB","DREB","REB","AST","TOV","STL","BLK","PF","X.FGA_2PT","X.FGA_3PT","X.PTS_2PT_PITP","X.PTS_2PT_MR","X.PTS_3PT","X.PTS_FT","CAS_FREQ","PULLUP_FREQ","PASSES_MADE","TOUCHES","ELBOW_TOUCHES","POST_UPS","PAINT_TOUCHES")


plot <- plot_ly(Data, x = ~grupo, y = ~PTS, type = "box", name = "PTS",color="orange",
marker = list(color = "lightgrey", line = list(color = "red", width = 1.5)), line = list(color = "black")) %>%
  layout(title = list(
    text = "Boxplot de cada grupo para cada variable",
    x = 0.1),
  xaxis = list(title = "Grupo"),
  yaxis = list(title = "Valor"),
  showlegend = FALSE,
  updatemenus = list(
    list(
      buttons = lapply(variable_list, function(variable) {
        list(
          method = "restyle",
          args = list(list(y = list(Data[[variable]]))),
          label = variable
        )
      }),
      direction = "down",
      active = 0,
      x = 1.15,
      xanchor = "right",
      y = 1.15,
      yanchor = "top"
    )))


plot



Grupo 1: Superestrellas - élite en casí todo

grupo1= Data %>% filter(grupo==1)
grupo1


Es impresionante lo dominante que los jugadores de este grupo son en la cancha. Son sobresalientes en puntos, postups, rebotes, asistencias, tiros libres, porcentaje de tiros de campo y bloqueos. Aunque frecuentan hacer unos más que otros, muestran capacidad de anotar el balón desde cualquier zona y de cualquier estilo. Es importante notar que estos son jugadores altos; son clasificados con la posición tradicional “power forward” o “centro”. Son los máximos ejemplares de lo que mencionamos sobre la evolución de los jugadores y del deporte.

Grupo 2: Estrellas dominantes con el balón

grupo2= Data %>% filter(grupo==2)
grupo2


Los de este grupo son también estrellas del juego. Tienen entre los valores más altos en puntos, asistencias y tiros de 3 puntos encestados. El equipo confía en ellos para tener el balón en mano y producir, visto por altos valores en posesiones de balón, tiros de campo lanzados y tiros libres lanzados. Muestran capacidad de anotar desde todas las zonas y todas las formas, excepto post-ups. Sin embargo, es de los grupos con menores porcentajes de tiros de campo. Se le puede atribuir a que es sumamente difícil ser muy eficiente con un alto volúmen de tiros intentados, espcialmente cuando muchos son desde el perímetro. También es de los grupos con mayores pérdidas de balón. Esto puede ser porque a medida que más tienes el balón en mano más son los chances de cometer errores.

Grupo 3: Estrellas Anotadores

grupo3= Data %>% filter(grupo==3)
grupo3


El grupo 3 son también jugadores estrellas de alto rendimiento. Muestran capacidad de anotar desde todas las zonas y todos los estilos, incluso post-ups a diferencia del grupo 2. Tienen un porcentaje de tiros de campo más alto, más rebotes y menos asistencias que el grupo 2. Mientras que el grupo 2 encesta más tiros de 3 puntos, este encesta más tiros libres.

Grupo 4: Buenos Tiradores

grupo4= Data %>% filter(grupo==4)
grupo4


Contiene muy buenos jugadores, aunque son promedio en muchas de las áreas. Se destacan por ser buenos tiradores. Comparado con otros grupos, sus valores en porcentaje de puntos anotados con tiros de 3 puntos son altos. Tienen variabilidad alta en algunas de las variables.

Grupo 5: Centros No Tradicionales

grupo5= Data %>% filter(grupo==5)
grupo5


Este grupo tiene características similares a un centro tradicional. Tienen muchos valores parecidos al grupo 8, como altos valores en rebotes, bloqueos, porcentaje de tiros de campo y posesiones en la pintura. Sin embargo, sí son capaces de expandir su rol más allá del de un centro tradicional. Es decir, pueden manejar el balón, tienen capacidad de lanzar desde las áreas de media distancia y tres puntos, etc. Esto se nota a través de números más elevados en comparación con el grupo 8 en puntos, asistencias, tiro de campo de tres puntos encestados y post-ups, por ejemplo.

Grupo 6: Buenos facilitadores (“playmakers”)

grupo6= Data %>% filter(grupo==6)
grupo6


Este grupo es interesante ya que tiene jugadores clasificados en todas las cinco posiciones tradionales. Tienen valores altos en asistencias, pases, posesiones de balón y pérdidas de balón. Sin embargo, tienen valores bajos en puntos y tiros de campo de 3 puntos encestados. Ofensivamente, tienden a manejar el balón no con la intención de anotar, sino crear las jugadas ofensivas y facilitarle un buen tiro a sus compañeros mediante los pases. Parece que su conocimiento de las jugadas de baloncesto les ayuda en el lado defensivo, ya que el 90% promedia al menos 1 robo por partido. Es decir, pueden leer las jugadas del otro equipo e interceptarle los pases.

Grupo 7: Jugadores Promedio (“role-players”)

grupo7= Data %>% filter(grupo==7)
grupo7


Son jugadores promedio en casi todas las métricas, pero se destacan un poco por su capacidad de lanzar desde el área de 3 puntos. Este es el grupo más grande en número de jugadores y muestra una variabilidad en los datos. Dentro del grupo unos son significativamente más productivos para su equipo o tienen más destrezas que otros.

Grupo 8: Centros Tradicionales

grupo8= Data %>% filter(grupo==8)
grupo8


Tradicionalmente, el jugador más alto del equipo se le designa la posición “centro” y se encarga únicamente de dominar la zona de la pintura tanto ofensiva como defensivamente. Las características de este grupo van en conjunto con esta definición. Tienen entre los valores más altos en porcentaje de tiros de campo, bloqueos, rebotes y posesiones en la pintura. No tienden a lanzar ni del área de media distancia ni de tres puntos. Tampoco son muy buenos con tiros libres, ya que tienen porcentajes menores a otros grupos. Nos enseñan que todavía existen “centros tradicionales” con rol muy definido.

Grupo 9: Jugadores bajo promedio

grupo9= Data %>% filter(grupo==9)
grupo9


Estos son los jugadores con menor desempeño. Dado a que su variabilidad es sumamente alta, no podemos identificarlos con un rol en particular. Se encuentran debajo del promedio en casi todas las métricas.

Conclusiones

Bibliografía


Competize. (2023). Historia del baloncesto y de la NBA 🏀 Origen del basquetbol en España. COMPETIZE. https://www.competize.com/blog/historia-baloncesto-nba-origen-basquetbol-espana/

Facundo. (2022, 25 enero). Historia del baloncesto: Origen y evolución del basket. MIDEPORTE.TOP. https://mideporte.top/baloncesto/historia-del-basket/

Fenichel, A. (2022). The Modernization of NBA Offenses and Why Small Ball Is Here to Stay. The Analyst. https://theanalyst.com/na/2021/03/the-modernization-of-nba-offenses-and-why-small-ball-is-here-to-stay/

NBA. (2022). Qué es la NBA y cómo funciona. NBA ID - Noticias: Qué es la NBA y cómo funciona. https://spain.id.nba.com/noticias/nba-que-es-como-funciona

Apéndice

Traeremos a uso una base de datos suplementaria que contiene los salarios de los jugadores para esta temporada. La misma fue extraída de la página de ESPN, otra página de cobertura de deportes. (http://www.espn.com/nba/salaries)

# Los datos fueron extraídos de la fuente a un archivo Excel y guardado localmente como "Salaries.csv"
Salaries <- read.csv("Salaries.csv")
Salaries


Le haremos un “merge” con la base de datos que trabajamos para el clustering.

Data$PLAYER <- row.names(Data)
Data_masSalarios <- left_join(Data,Salaries, by = join_by(PLAYER == NAME))
row.names(Data_masSalarios) <- Data_masSalarios$PLAYER
Data$PLAYER <- NULL
Data_masSalarios$PLAYER <- NULL
sum(is.na(Data_masSalarios))
## [1] 2

Imputamos datos faltantes porque habían jugadores que su salario no estaba reportado.

Imput_reg1 <- mice(Data_masSalarios,method="norm.predict",print=F)
Complete_reg1 <- mice::complete(Imput_reg1)
Complete_reg1


Podemos gráficar el salario contra cualquier variable mediante un scatterplot y hacer un modelo de regresión lineal. Lo haremos con puntos, ya que es la más importante porque el objetivo principal del deporte es anotar. Además queremos ver si captamos diferencias en salario entre los nueve grupos que formamos en el modelo de clustering jerárquico.

plot2 <- plot_ly(data = Complete_reg1, x = ~PTS, y = ~SALARY, color = ~as.factor(grupo), type="scatter",mode="markers",
        text = ~paste("Jugador: ", rownames(Complete_reg1))) %>%
  add_trace(x = ~PTS, y = fitted(lm(SALARY ~ PTS, data = Complete_reg1)), mode = "lines", name = "Regression Line") %>%  layout(title = "Puntos contra Salarios, por Grupo")


plot2