¿Cómo ha cambiado el ESTILO de la ACB? — la carta de tiro, temporada a temporada¶
basketballonpampers · informe de análisis de datos
En síntesis. Estudio hermano del de los Four Factors, pero un nivel más fino: de dónde y cuándo tira la ACB, temporada a temporada, con la carta de tiro (2016/17–2025/26, diez temporadas, ~387.000 tiros; el cuándo —tramos de reloj— solo desde 2020/21, ver método). El movimiento es nítido y de una sola dirección: más triple (40,0 → 44,2 % de los tiros, r 0,93), muere la media distancia (13,9 → 9,8 %, r −0,90) y también cede la pintura (19,8 → 17,4 %, r −0,83) mientras el aro sube (26,3 → 28,5 %, r 0,62). Y más fino aún: dentro de los triples, cada vez más de esquina (23,9 → 28,5 %, r 0,70) — el tiro más eficiente. En cambio, el ritmo de tiro (tramos de reloj) y el % asistido no muestran tendencia sólida. Conclusión: la modernización de la ACB es un cambio de selección de tiro (media y pintura → triple y aro, y triples más inteligentes), no de tempo ni de circulación de balón.
La pregunta¶
El estudio de los Four Factors mostró que la ACB tira más de tres cada año. Este baja al detalle: ¿ese cambio es de dónde se tira (dieta por zona), de cuándo (tramo de reloj) o de cómo se generan los tiros (asistidos)? La carta de tiro lo dice.
Cómo lo medimos (honesto)¶
- Nivel LIGA, una fila por temporada: cada indicador se calcula sobre todos los tiros de la
temporada (
silver_tirodel medallion ACB). - Diez temporadas (2016/17–2025/26) para el dónde; seis (2020/21→) para el cuándo. Las coordenadas de 2016-2019 llegan en una rejilla más gruesa (1 % de pista, ~28 cm), suficiente para las zonas. El reloj de posesión del play-by-play anterior a 2020/21, en cambio, no es comparable (registra el doble de tiros en los primeros 3 segundos con el ritmo de partido plano: un artefacto de registro, no baloncesto), así que los tramos solo se leen desde 2020/21.
- Zonas agrupadas (aro, pintura, media, triple) y tramos de reloj de posesión (1-8 / 9-16 / 17+ s), la convención del producto. % asistido = canastas tras pase sobre el total de canastas.
- Tendencia = recta + correlación con el año (|r| ≳ 0,6 = sólida). Descriptivo, 10 puntos (6 en los tramos): se leen las direcciones, no se sobreinterpreta el decimal.
1. Los datos, temporada a temporada¶
import warnings; warnings.filterwarnings("ignore")
from pathlib import Path
import numpy as np, pandas as pd
import matplotlib.pyplot as plt
BG="#0c0c0e"; PANEL="#151517"; INK="#ededf0"; MUTED="#8a8a93"; ACCENT="#e8772e"
GRID="#2a2a2e"; POS="#3fb27f"; NEG="#d8584f"; BLUE="#4f93c7"
plt.rcParams.update({
"figure.facecolor": BG, "axes.facecolor": BG, "savefig.facecolor": BG,
"axes.edgecolor": GRID, "axes.labelcolor": INK, "text.color": INK,
"xtick.color": MUTED, "ytick.color": MUTED, "grid.color": GRID,
"axes.grid": True, "grid.alpha": 0.30, "grid.linewidth": 0.6,
"figure.figsize": (9, 5), "figure.dpi": 110,
"font.size": 11, "axes.titlesize": 12.5, "axes.titleweight": "bold",
"axes.spines.top": False, "axes.spines.right": False,
})
for cand in [Path("../datasets-acb"), Path("analisis/datasets-acb"), Path("../../analisis/datasets-acb")]:
if cand.exists():
BASE = cand; break
t = pd.read_parquet(BASE/"silver"/"silver_tiro"); t["temporada"] = t.temporada.astype(int)
MID = {"Mid izq","Mid der","Mid central"}; CORN = {"Corner izq","Corner der"}
t["rim"]=t.zona=="Aro"; t["paint"]=t.zona=="Pintura"; t["media"]=t.zona.isin(MID)
t["tres"]=t.valor==3; t["corner"]=t.zona.isin(CORN)
t["rapido"]=t.tramo=="1-8 s · rápido"; t["medio"]=t.tramo=="9-16 s · medio"; t["elab"]=t.tramo=="17+ s · elaborado"
t["asis_make"]=t.anotado & t.asistido
g = t.groupby("temporada")
tab = pd.DataFrame({
"% aro": g.rim.mean()*100,
"% pintura": g.paint.mean()*100,
"% media": g.media.mean()*100,
"% triple": g.tres.mean()*100,
"corner (de 3)": g.apply(lambda d: d.corner.sum()/d.tres.sum()*100),
"% rápido": g.rapido.mean()*100,
"% medio": g.medio.mean()*100,
"% elaborado": g.elab.mean()*100,
"% asistido": g.apply(lambda d: d.asis_make.sum()/d.anotado.sum()*100),
}).round(1)
# El reloj de posesión del play-by-play anterior a 2020/21 no es comparable (registra el doble de
# tiros en los primeros 3 s, con el ritmo plano): los TRAMOS solo se leen desde 2020/21.
TRAMOS = ["% rápido", "% medio", "% elaborado"]; TRAMOS_DESDE = 2020
tab.loc[tab.index < TRAMOS_DESDE, TRAMOS] = np.nan
yr = np.array(tab.index) # temporadas presentes en la carta de tiro
tab.index = [f"{y}/{str(y+1)[2:]}" for y in tab.index]
print("Tiros analizados:", len(t))
print(tab.to_string())
Tiros analizados: 387477
% aro % pintura % media % triple corner (de 3) % rápido % medio % elaborado % asistido
2016/17 26.3 19.8 13.9 40.0 23.9 NaN NaN NaN 51.3
2017/18 25.6 20.4 13.9 40.1 25.5 NaN NaN NaN 52.4
2018/19 25.2 20.8 12.4 41.6 24.7 NaN NaN NaN 51.5
2019/20 27.7 18.6 12.8 40.9 21.1 NaN NaN NaN 51.2
2020/21 29.5 18.0 11.1 41.4 24.6 25.3 34.7 40.0 48.8
2021/22 28.2 19.1 11.1 41.6 25.3 24.2 34.0 41.8 47.8
2022/23 28.7 16.6 12.0 42.7 26.0 23.4 34.9 41.6 49.4
2023/24 27.7 17.7 11.6 43.1 27.2 23.6 34.5 41.9 50.7
2024/25 27.4 17.1 10.3 45.2 26.6 24.0 34.6 41.4 51.1
2025/26 28.5 17.4 9.8 44.2 28.5 24.2 37.6 38.2 48.2
def tendencia(c):
"""Recta + correlación con el año sobre los puntos disponibles de la palanca (los tramos empiezan en 2020/21)."""
v = tab[c].values.astype(float); m = ~np.isnan(v)
x, vv = yr[m], v[m]
b1, b0 = np.polyfit(x, vv, 1); r = np.corrcoef(x, vv)[0, 1]
return x, vv, b0, b1, r
filas = []
for c in tab.columns:
x, v, b0, b1, r = tendencia(c)
tend = "SUBE" if r>0.6 else ("BAJA" if r<-0.6 else "plana")
filas.append([c, f"{x[0]%100:02d}/{(x[0]+1)%100:02d}", round(v[0],1), round(v[-1],1), round(v[-1]-v[0],1), len(x), round(r,2), tend])
e1 = f"{yr[-1]%100:02d}/{(yr[-1]+1)%100:02d}"
trend = pd.DataFrame(filas, columns=["palanca","desde","inicio",e1,"Δ","n temp.","r(año)","tendencia"])
print(trend.to_string(index=False))
palanca desde inicio 25/26 Δ n temp. r(año) tendencia
% aro 16/17 26.3 28.5 2.2 10 0.62 SUBE
% pintura 16/17 19.8 17.4 -2.4 10 -0.83 BAJA
% media 16/17 13.9 9.8 -4.1 10 -0.90 BAJA
% triple 16/17 40.0 44.2 4.2 10 0.93 SUBE
corner (de 3) 16/17 23.9 28.5 4.6 10 0.70 SUBE
% rápido 20/21 25.3 24.2 -1.1 6 -0.47 plana
% medio 20/21 34.7 37.6 2.9 6 0.66 SUBE
% elaborado 20/21 40.0 38.2 -1.8 6 -0.36 plana
% asistido 16/17 51.3 48.2 -3.1 10 -0.55 plana
Lectura del cuadro. Cuatro cambios sólidos en diez temporadas: el % triple sube (r 0,93) y el corner (de 3) sube (r 0,70); la media distancia (r −0,90) y la pintura (r −0,83) bajan; el aro sube algo menos (r 0,62). Los tramos (seis temporadas) y el % asistido no tienen tendencia sólida: el asistido baja levemente (r −0,55) sin llegar al umbral.
2. La dieta de tiro: la media distancia muere, el triple manda¶
fig, ax = plt.subplots(figsize=(9.4, 5))
for c,col in [("% aro",MUTED),("% pintura",BLUE),("% media",NEG),("% triple",ACCENT)]:
v = tab[c].values.astype(float)
ax.plot(yr, v, "-o", color=col, lw=2.2, ms=5, label=f"{c} ({v[0]:.0f}→{v[-1]:.0f})")
ax.set_xticks(yr); ax.set_xticklabels([f"{y%100:02d}/{(y+1)%100:02d}" for y in yr])
ax.set_ylabel("% de los tiros del equipo")
ax.set_title("Dieta de tiro de la ACB por temporada · nivel liga", color=INK)
ax.legend(facecolor=PANEL, edgecolor=GRID, labelcolor=INK)
plt.tight_layout(); plt.show()
Lectura. El triple (naranja) crece con claridad y la media distancia (rojo) se encoge — el cambio moderno de libro: cambiar el tiro de dos largo (ineficiente) por el triple. Con diez temporadas se ve además que la pintura (el dos cercano que no es aro) también cede y que el aro gana: el cambio es media y pintura → triple y aro — dejar la zona muerta y el dos intermedio, no "atacar más" sin más.
3. Más fino: triples cada vez más de esquina¶
No solo se tiran más triples; se eligen mejores triples. La esquina es el triple más corto (6,60 m) y más eficiente — y su peso dentro de los triples sube todos los años.
fig, ax = plt.subplots(figsize=(9.2, 4.6))
v = tab["corner (de 3)"].values.astype(float)
ax.plot(yr, v, "-o", color=POS, lw=2.4, ms=6)
b1,b0 = np.polyfit(yr,v,1); ax.plot(yr, b0+b1*yr, "--", color=MUTED, lw=1.2)
for x,val in zip(yr,v): ax.text(x, val+0.2, f"{val:.1f}%", ha="center", color=INK, fontsize=9, fontweight="bold")
ax.set_xticks(yr); ax.set_xticklabels([f"{y%100:02d}/{(y+1)%100:02d}" for y in yr])
ax.set_ylabel("% de los triples que son de esquina")
ax.set_title(f"Triples de esquina · {v[0]:.0f}% → {v[-1]:.0f}% (r={np.corrcoef(yr,v)[0,1]:+.2f})", color=INK)
plt.tight_layout(); plt.show()
Lectura. En 2016/17, uno de cada cuatro triples era de esquina; en 2025/26, casi tres de cada diez. Es optimización de la calidad del tiro — la ACB no solo tira más de tres, tira mejores tres.
4. Lo que NO cambia: el ritmo de tiro y el pase¶
fig, axes = plt.subplots(1, 2, figsize=(11, 4.3))
# tramos (solo desde 2020/21: el reloj de posesión anterior no es comparable)
for c,col in [("% rápido",POS),("% medio",BLUE),("% elaborado",ACCENT)]:
x, v, *_ = tendencia(c)
axes[0].plot(x, v, "-o", color=col, lw=2, ms=4, label=c)
axes[0].set_title("Tramos de reloj (cuándo se tira) · desde 2020/21", color=INK)
axes[0].set_xticks(x); axes[0].set_xticklabels([f"{y%100:02d}" for y in x])
axes[0].legend(facecolor=PANEL, edgecolor=GRID, labelcolor=INK, fontsize=9)
# asistido (10 temporadas)
x, v, b0, b1, r = tendencia("% asistido")
axes[1].plot(x, v, "-o", color=ACCENT, lw=2.2, ms=5)
axes[1].set_ylim(min(v)-3, max(v)+3)
axes[1].set_title(f"% asistido (mover el balón) · r={r:+.2f}", color=INK)
axes[1].set_xticks(x); axes[1].set_xticklabels([f"{y%100:02d}" for y in x])
plt.tight_layout(); plt.show()
Lectura. Ni el reparto de tramos (seis temporadas, desde 2020/21) ni el % asistido (diez) tienen tendencia sólida: el tramo medio sube algo (r 0,66) a costa de rápidos y elaborados sin un patrón claro, y el asistido baja levemente sin llegar al umbral (r −0,55). El juego no se ha vuelto más de transición ni de más pase: lo que ha cambiado es qué tiro se elige, no el ritmo ni la circulación. (Ojo: el ritmo de PARTIDO —posesiones— sí sube, como vimos en los Four Factors; eso es jugar más posesiones, distinto de cuándo se tira dentro de cada una.)
5. Conclusiones¶
- La modernización de la ACB es de selección de tiro: media y pintura → triple y aro (triple 40 → 44 %, media 14 → 10 %, pintura 20 → 17 %, aro 26 → 29 % en diez temporadas). El cambio no es "atacar más el aro" a secas: es dejar la zona muerta y el dos intermedio.
- Y triples más inteligentes: dentro de los tres, cada vez más de esquina (24 → 29 %), el más eficiente. Optimización de calidad, no solo de volumen.
- Lo que NO cambia: el reparto por tramos de reloj y el % asistido — el juego no es más de transición ni de más pase; es mejor elegido.
Cautelas (honestidad)¶
- Diez temporadas para el dónde y seis para el cuándo: el reloj de posesión del play-by-play anterior a 2020/21 no es comparable, y las coordenadas de 2016-2019 vienen en una rejilla más gruesa (válida para zonas, no para el decimal). Estudio separado del de los Four Factors a propósito.
- Nivel liga; posesiones/tramos con la maquinaria del motor, consistentes entre temporadas desde 2020/21.
- Descriptivo: describe la evolución del estilo, no predice la próxima temporada.