Los gráficos de radar, también conocidos como gráficos de araña o Radar Charts, son representaciones visuales que permiten comparar múltiples variables en un solo gráfico circular. En el fútbol, estos gráficos se utilizan para evaluar el rendimiento de los jugadores en diversas áreas, destacando sus cualidades de manera gráfica y fácilmente interpretable.
Este tipo de gráficos pueden generarse gracias a la librería MplSoccer. Antes de empezar, te invito a que visites este enlace y te familiarices con la documentación y ejemplos. En su documentación, nos proporciona varios ejemplos y código que podemos utilizar para practicar. Precisamente, vamos a reutilizar partes del código para la práctica que se presenta en este artículo.
En la primera parte de «Aprendiendo Python con Fútbol«, revisamos conceptos como variables, listas, importación y uso de librerías. Varios de estos puntos los abordaremos en esta práctica, dando un salto a un nivel más avanzado. El código que se presenta está elaborado de tal manera que puedas reforzar los conceptos y, sobre todo, puedas reutilizarlo y modificarlo a tu gusto. ¡Empecemos!
Importación de librerías
from mplsoccer import Radar, FontManager, grid
import matplotlib.pyplot as plt
Jugadores que vamos a comparar
Hacemos uso de variables, asignamos los nombres de los jugadores, equipos a los que pertenecen y el color en formato hexadecimal, en este enlace puedes acceder a una amplia gama de colores y obtener su código.
player1_name = "Bernardo Silva"
player1_team = "Manchester City"
player1_color = "#29B6F6"
player2_name = "Leroy Sané"
player2_team = "Bayern Munich"
player2_color = "#C62828"
Parámetros que vamos a medir
En este caso, vamos a hacer uso de seis parámetros, para cada parámetro ingresamos el valor más bajo y más alto de medición, y luego los valores que posee cada jugador. Es decir, si deseamos representar el parámetro «Regates» con una escala de 0 a 4 en el gráfico nos permitirá pintar la estadística de cada jugador, para esto tenemos las variables param_player1 y param_player2 en donde ingresaremos los valores que pertenecen a los jugadores.
param1= "Goles"
param1_low= 0
param1_high= 4
param1_player1= 1
param1_player2= 0
param2= "Asistencias"
param2_low= 0
param2_high= 4
param2_player1= 1
param2_player2= 0
param3= "Remates a Puerta"
param3_low= 0
param3_high= 4
param3_player1= 1
param3_player2= 4
param4= "Pases completados"
param4_low= 8
param4_high= 32
param4_player1= 28
param4_player2= 28
param5= "Toques"
param5_low= 16
param5_high= 64
param5_player1= 56
param5_player2= 53
param6= "Regates"
param6_low= 0
param6_high= 4
param6_player1= 3
param6_player2= 3
Agrupamos las variables en Listas
Una lista es una estructura de datos en Python que permite almacenar múltiples elementos bajo un mismo nombre. Para este caso, agrupamos las variables que contienen los nombres de los parámetros en params, los valores de escalas en low y high, finalmente los valores de cada jugador en listas independientes; la finalidad de esto, es tener los datos segmentados para lograr presentarlos en el gráfico.
#Se cargan variables para su uso en una Lista
params = [param1, param2, param3, param4, param5 , param6]
# Agrupamos los límites inferior(low) y superior(high)
low = [param1_low, param2_low, param3_low, param4_low, param5_low, param6_low, ]
high = [param1_high, param2_high, param3_high, param4_high, param5_high, param6_high]
#Almacenamos los valores de ambos jugadores
player1_values = [param1_player1, param2_player1, param3_player1, param4_player1, param5_player1, param6_player1]
player2_values = [param1_player2, param2_player2, param3_player2, param4_player2, param5_player2, param6_player2]
Tipografía
Hacemos uso de tipografías externas para aplicar en el gráfico
URL1 = ('https://raw.githubusercontent.com/googlefonts/SourceSerifProGFVersion/main/fonts/'
'SourceSerifPro-Regular.ttf')
serif_regular = FontManager(URL1)
URL2 = ('https://raw.githubusercontent.com/googlefonts/SourceSerifProGFVersion/main/fonts/'
'SourceSerifPro-ExtraLight.ttf')
serif_extra_light = FontManager(URL2)
URL3 = ('https://raw.githubusercontent.com/google/fonts/main/ofl/rubikmonoone/'
'RubikMonoOne-Regular.ttf')
rubik_regular = FontManager(URL3)
URL4 = 'https://raw.githubusercontent.com/googlefonts/roboto/main/src/hinted/Roboto-Thin.ttf'
robotto_thin = FontManager(URL4)
URL5 = ('https://raw.githubusercontent.com/google/fonts/main/apache/robotoslab/'
'RobotoSlab%5Bwght%5D.ttf')
robotto_bold = FontManager(URL5)
Configurando el Radar
En este bloque de código, se insertan los valores de los parámetros y escalas, no es necesario que realices ninguna modificación, salvo si deseas cambiar el número de anillos en la variable num_rings.
radar = Radar(params, low, high,
# whether to round any of the labels to integers instead of decimal places
round_int=[False]*len(params),
num_rings=4, # the number of concentric circles (excluding center circle)
# if the ring_width is more than the center_circle_radius then
# the center circle radius will be wider than the width of the concentric circles
ring_width=1, center_circle_radius=1)
Dibujando el Radar
Aquí viene la magia de MplSoccer, no te rompas la cabeza tratando de entender el código 😉 pero, si lo revisas vas a poder modificar algunos tamaños de tipografía, colores o pie de la imagen.
# creating the figure using the grid function from mplsoccer:
fig, axs = grid(figheight=14, grid_height=0.915, title_height=0.06, endnote_height=0.025,
title_space=0, endnote_space=0, grid_key='radar', axis=False)
# plot radar
radar.setup_axis(ax=axs['radar']) # format axis as a radar
rings_inner = radar.draw_circles(ax=axs['radar'], facecolor='#E0E0E0', edgecolor='#BDBDBD')
radar_output = radar.draw_radar_compare(player1_values, player2_values, ax=axs['radar'],
kwargs_radar={'facecolor': player1_color, 'alpha': 0.6},
kwargs_compare={'facecolor': player2_color, 'alpha': 0.6})
radar_poly, radar_poly2, vertices1, vertices2 = radar_output
range_labels = radar.draw_range_labels(ax=axs['radar'], fontsize=16,
fontproperties=robotto_thin.prop)
param_labels = radar.draw_param_labels(ax=axs['radar'], fontsize=22,
fontproperties=robotto_thin.prop)
axs['radar'].scatter(vertices1[:, 0], vertices1[:, 1],
c=player1_color, edgecolors=player1_color, marker='o', s=100, zorder=2)
axs['radar'].scatter(vertices2[:, 0], vertices2[:, 1],
c=player2_color, edgecolors=player2_color, marker='o', s=100, zorder=2)
# adding the endnote and title text (these axes range from 0-1, i.e. 0, 0 is the bottom left)
# Note we are slightly offsetting the text from the edges by 0.01 (1%, e.g. 0.99)
endnote_text = axs['endnote'].text(0.99, 0.5, 'www.futbolcondatos.com', fontsize=15,
fontproperties=robotto_thin.prop, ha='right', va='center')
title1_text = axs['title'].text(0.01, 0.65, player1_name, fontsize=25, color=player1_color,
fontproperties=robotto_bold.prop, ha='left', va='center')
title2_text = axs['title'].text(0.01, 0.25, player1_team, fontsize=20,
fontproperties=robotto_thin.prop,
ha='left', va='center', color=player1_color)
title3_text = axs['title'].text(0.99, 0.65, player2_name, fontsize=25,
fontproperties=robotto_bold.prop,
ha='right', va='center', color=player2_color)
title4_text = axs['title'].text(0.99, 0.25, player2_team, fontsize=20,
fontproperties=robotto_thin.prop,
ha='right', va='center', color=player2_color)
¿Te gustó el resultado final? Puedes utilizar este código para comparar el rendimiento de jugadores y si deseas de equipos, solo es cuestión de hacer los ajustes necesarios. En un entorno cada vez más influenciado por el análisis de datos, los gráficos de radar se destacan como una herramienta valiosa para evaluar y mejorar continuamente el rendimiento en el fútbol.
El código utilizado en este artículo lo puedes revisar y descargar desde mi repositorio de GitHub.