0% encontró este documento útil (0 votos)
30 vistas27 páginas

Cap 4 Es

Cpitulo libro apuestas

Cargado por

Ricardo Ayala
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
30 vistas27 páginas

Cap 4 Es

Cpitulo libro apuestas

Cargado por

Ricardo Ayala
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Suscríbete a DeepL Pro para poder traducir archivos de mayor tamañ

Más información disponible en [Link]/pro.

4
Datos de partidos y tablas de clasificación

Gran parte de los análisis relacionados con el fútbol consisten en recopilar


estadísticas de datos históricos de partidos y predecir las posiciones de la liga al final
de la temporada (EoS). Los científicos de datos que trabajan en el deporte
profesional pueden obtener mucha información útil mediante el análisis de datos
históricos y dedican mucho tiempo a intentar identificar características (métricas)
que expliquen el rendimiento de los equipos. En este capítulo, nos centraremos en
las técnicas para capturar métricas de rendimiento a partir de datos históricos de
partidos, ya que pueden ser útiles para predecir la posición probable en la liga EoS.
Además, en este capítulo, mostraremos cómo compilar estadísticas de rendimiento
en casa y fuera a partir de datos históricos de partidos, así como obtener estadísticas
de partidos cara a cara (H2H) para partidos equivalentes en temporadas anteriores.

4.1 Recopilación de estadísticas de rendimiento de


equipos a partir de datos históricos de
partidos
Los datos históricos de los partidos pueden ser un excelente recurso para evaluar el
rendimiento de los equipos de fútbol. Sin embargo, organizar los datos de forma que
puedan analizarse fácilmente suele ser una tarea complicada, sobre todo porque los
equipos suelen jugar entre sí tanto en casa como fuera, algo que puede causar
confusión si no se maneja correctamente. Además, a menudo queremos aumentar
los conjuntos de datos con métricas de rendimiento que puedan derivarse de los
datos de los partidos. Por ello, en esta sección veremos cómo los datos históricos de
los partidos pueden ampliarse y utilizarse para producir estadísticas de rendimiento.
Los conjuntos de datos sobre el rendimiento de los partidos suelen incluir
estadísticas relativas a los tiros intentados y a los tiros a puerta, que pueden utilizarse
para producir métricas derivadas, como el coeficiente de tiros totales (TSR), que es
un indicador muy utilizado del rendimiento de los equipos (para más detalles sobre
el TSR, véase el capítulo 5). El TSR se calcula de la siguiente manera:
SF
TSR = (4.1)
SF+ SA
donde SF es el número de tiros a favor del equipo y SA es el número de tiros en
contra.

DOI: 10.1201/9781003328568-4 103


104 Análisis del fútbol

En el Ejemplo 4.1, aumentaremos los datos de los partidos de la Premier League


inglesa (EPL) de la temporada 2020-2021 calculando el TSR de los equipos local y
visitante, así como el número de puntos otorgados a cada equipo.

EJEMPLO 4.1: AUMENTO DE LOS DATOS HISTÓRICOS DE LOS


PARTIDOS
Antes de empezar a codificar, siempre es una buena práctica borrar primero las variables
y datos existentes del espacio de trabajo de RStudio, ya que podrían interferir con el
nuevo script. Esto se puede hacer fácilmente usando la siguiente línea de código R,
que, aunque no es muy memorable, funciona muy bien.

rm(list= ls()) # Esto borra todas las variables del espacio de trabajo

Ahora que tenemos una pizarra en blanco, los datos pueden ser importados a R en
formato CSV y mostrados usando el código de abajo.
Este ejemplo utiliza datos históricos de: [Link]
[Link] para la temporada EPL 2020-2021. Sin embargo, no utilizaremos todas
las variables del conjunto de datos. Aquí sólo utilizaremos las 16 primeras variables,
que son:

• Div= División de la liga


• Fecha= Fecha del partido (dd/mm/aa)
• Equipo local= Equipo local
• AwayTeam= Equipo visitante
• FTHG= Goles a tiempo completo del equipo local
• FTAG= Goles del equipo visitante a tiempo completo
• FTR= Resultado a tiempo completo (H= victoria local, D= empate, A= victoria
visitante)
• HTHG= Goles del equipo local en el descanso
• HTAG= Goles del equipo visitante en el descanso
• HTR= Resultado al descanso (H= victoria local, D= empate, A= victoria visitante)
• Árbitro= Árbitro del partido
• HS= Disparos del equipo local
• AS= Disparos del equipo visitante
• HST= Disparos a puerta del equipo local
• AST= Disparos a puerta del equipo visitante

Los datos pueden cargarse en R utilizando el siguiente código, que selecciona sólo las
16 primeras variables.

# Cargar datos (NB. Aquí seleccionamos sólo las 16 primeras variables).


EPL2020_data <- head([Link]('[Link] 380)[,1:16]

# Inspeccionar los datos


names(EPL2020_data)
Datos de los partidos y tablas de 105
clasificación

##
[1] "Div" "Fecha" "Hora" "HomeTeam" "EquipoAlejad "FTHG"
o"
[7] "FTAG" "FTR "HTHG" "HTAG "HTR" "Árbitro"
[13] "HS" "AS" "HST" "AST

A partir de esto, podemos ver que hemos incluido algunas variables que son irrelevantes.
Así que, para facilitar el uso, eliminaremos las variables "Div", "HTHG", "HTAG",
"HTR" y "Referee", que no nos interesan aquí.

dat< - EPL2020_data[,c("Date", "HomeTeam", "AwayTeam", "FTHG", "FTAG", "FTR", "HS", "AS", "HST",
"AST")] # Esto crea un marco de datos de trabajo

head(dat) # Muestra las seis primeras filas de dat

Lo que produce:

##
Fecha Equipo local Equipo visitante FTHG FTAG FTR HS AS HST AST
1 12/09/2020 Fulham Arsenal 0 3 A 5 13 2 6
2 12/09/2020 Crystal Palace Southampton 1 0 H 5 9 3 5
3 12/09/2020 Liverpool Leeds 4 3 H 22 6 6 3
4 12/09/2020 West Ham Newcastle 0 2 A 15 15 3 2
5 13/09/2020 West Brom Leicester 0 3 A 7 13 1 7
6 13/09/2020 Tottenham Everton 0 1 A 9 15 5 4

Ahora podemos aumentar los datos añadiendo nuevas variables derivadas. Para ello,
primero necesitamos crear algunas nuevas variables 'vacías' pobladas con NAs y
ceros en las que almacenar las estadísticas derivadas.

dat["GD"]< - NA # Crea una nueva columna para la diferencia de goles poblada con NAs
dat["TG"]< - NA # Crea una nueva columna para el total de goles marcados poblada con
NAs dat["HTSR"]< - NA # Crea una variable de ratio de tiros del equipo local poblada con
NAs dat["ATSR"]< - NA # Crea una variable de ratio de tiros del equipo visitante poblada
con NAs dat["HPts"]< - 0 # Crea una variable de puntos del equipo local poblada con ceros
dat["APts"]< - 0 # Crea una variable de puntos del equipo visitante poblada con ceros

Una vez creadas las variables vacías, podemos calcular las estadísticas derivadas y
rellenar las variables de la siguiente manera:

dat$GD< - dat$FTHG - dat$FTAG


dat$TG< - dat$FTHG+ dat$FTAG
dat$HTSR< - round(dat$HS/(dat$HS+ dat$AS),3) # Aquí redondeamos a 3 decimales dat$ATSR< -
round(dat$AS/(dat$AS+ dat$HS),3) # Aquí redondeamos a 3 decimales

Calcular los puntos obtenidos en casa y fuera es un poco más complicado. Pero
esto se puede hacer con bastante facilidad utilizando un bucle for y cuatro sentencias
if, como se indica a continuación.
106 Análisis del fútbol

for(i en 1:nrow(dat)){
if(dat$FTR[i]== "H"){dat$HPts[i]< - 3}
if(dat$FTR[i]== "A"){dat$APts[i]< - 3}
if(dat$FTR[i]== "D") {dat$HPts[i]< - 1}
if(dat$FTR[i]== "D") {dat$APts[i]< - 1}
}
También podemos cambiar el nombre de algunas de las columnas del marco de datos.

colnames(dat)[colnames(dat)== 'FTHG']< - 'HG'


colnames(dat)[colnames(dat)== 'FTAG']< - 'AG'
colnames(dat)[colnames(dat)== 'FTR']< - 'Resultado'

Por último, podemos mostrar el nuevo marco de datos 'dat' aumentado.

head(dat) # Muestra sólo las seis primeras filas del marco de datos.

##
Fecha Equipo local Equipo visitante HG AG Resultado HS AS HST AST GD TG
1 12/09/2020 Fulham Arsenal 0 3 A 5 13 2 6 -3 3
2 12/09/2020 Crystal Palace Southampton 1 0 H 5 9 3 5 1 1
3 12/09/2020 Liverpool Leeds 4 3 H 22 6 6 3 1 7
4 12/09/2020 West Ham Newcastle 0 2 A 15 15 3 2 -2 2
5 13/09/2020 West Brom Leicester 0 3 A 7 13 1 7 -3 3
6 13/09/2020 Tottenham Everton 0 1 A 9 15 5 4 -1 1
HTSR ATSR HPts APts
1 0.278 0.722 0 3
2 0.357 0.643 3 0
3 0.786 0.214 3 0
4 0.500 0.500 0 3
5 0.350 0.650 0 3
6 0.375 0.625 0 3

Una vez descargados y ampliados los datos de los partidos tal y como se muestra
en el Ejemplo 4.1, es frecuente que queramos analizar el rendimiento de los distintos
equipos de la liga. Esto puede ser complicado porque los equipos de la liga juegan
tanto en casa como fuera, lo que significa que, al evaluar el rendimiento, tenemos
que distinguir entre los dos. Por lo tanto, al evaluar el rendimiento de los equipos
individuales, es útil convertir los datos en "a favor" y " en contra" en lugar de "en
casa" y "fuera", como se ilustra en el Ejemplo 4.2, que considera el rendimiento del
Liverpool durante la temporada 2020-2021.
Datos de los partidos y tablas de 107
clasificación

EJEMPLO 4.2: EXTRACCIÓN DE DATOS PARA EQUIPOS


INDIVIDUALES
Aquí evaluaremos el rendimiento del Liverpool durante la temporada 2020-2021. En
este caso, el Liverpool es el equipo objetivo (o de estudio).

[Link]< - "Liverpool" # NB. El nombre del equipo debe ir entre comillas.

A continuación, extraemos los datos sólo del equipo objetivo.

[Link]< - dat[dat$HomeTeam== [Link],] # Selecciona los partidos en casa del equipo


objetivo. [Link]< - dat[dat$AwayTeam== [Link],] # Selecciona los partidos fuera de casa
del equipo objetivo.

Ahora, necesitamos añadir una variable 'status' para indicar si un partido es en casa o
fuera.

[Link]["Status"]< - "Home" # Crea la nueva columna para indicar los partidos jugados en casa.
[Link]["Status"]< - "Away" # Crea la nueva columna para indicar los partidos jugados fuera.

A continuación, tenemos que cambiar los nombres de las variables para que sean
específicos de cada club (es decir, a favor y en contra en lugar de local y visitante).

home< - [Link] # Hacer copia duplicada del marco de datos sobre el que hacer cambios
away< - [Link] # Hacer copia duplicada del marco de datos sobre el que hacer cambios

En este punto, es una buena idea inspeccionar los marcos de datos, sólo para
comprobar que lo hemos hecho todo bien.

head(inicio)

##
Fecha Equipo local EquipoAlejado HG AG Resultado HS AS HST AST GD
3 12/09/2020 Liverpool Leeds 4 3 H 22 6 6 3 1
28 28/09/2020 Liverpool Arsenal 3 1 H 21 4 8 3 2
53 24/10/2020 Liverpool Sheffield United 2 1 H 17 13 5 2 1
62 31/10/2020 Liverpool West Ham 2 1 H 9 4 5 3 1
86 22/11/2020 Liverpool Leicester 3 0 H 24 11 13 4 3
106 06/12/2020 Liverpool Lobos 4 0 H 11 9 6 3 4
TG HTSR ATSR HPts APts Estado
3 7 0.786 0.214 3 0 Inici
o
28 4 0.840 0.160 3 0 Inici
o
53 3 0.567 0.433 3 0 Inici
o
62 3 0.692 0.308 3 0 Inici
o
86 3 0.686 0.314 3 0 Inici
o
106 4 0.550 0.450 3 0 Inici
o

cabeza(fuera)
108 Análisis del fútbol

##
Fecha Equipo local Equipo visitante HG AG Resultado HS AS HST AST GD TG
15 20/09/2020 Chelsea Liverpool 0 2 A 5 18 3 6 -2 2
38 04/10/2020 Aston Villa Liverpool 7 2 H 18 14 11 8 5 9
39 17/10/2020 Everton Liverpool 2 2 D 11 22 5 8 0 4
77 08/11/2020 Man City Liverpool 1 1 D 7 10 2 3 0 2
90 28/11/2020 Brighton Liverpool 1 1 D 11 6 3 2 0 2
115 13/12/2020 Fulham Liverpool 1 1 D 10 12 5 6 0 2
HTSR ATSR HPts APts Estado
15 0.217 0.783 0 3 Fuera
de
casa
38 0.562 0.438 3 0 Fuera
de
casa
39 0.333 0.667 1 1 Fuera
de
casa
77 0.412 0.588 1 1 Fuera
90 0.647 0.353 1 1 Fuera
115 0.455 0.545 1 1 Fuera

De esto se desprende que seguimos describiendo las cosas en términos de goles


en casa y fuera, en lugar de goles a favor y en contra del Liverpool, que es mucho
más útil. Por lo tanto, tenemos que cambiar los nombres de las variables en los
marcos de datos "local" y "visitante" para reflejar esto. En R, hay muchas formas de
cambiar los nombres de las variables. Por ejemplo, utilizamos la función 'colnames'
en el Ejemplo 4.1 para realizar esta tarea. Sin embargo, este enfoque tiende a ser
engorroso cuando hay una necesidad de cambiar múltiples nombres de variables al
mismo tiempo. Así que, en este ejemplo, utilizaremos en su lugar el comando
'rename' del paquete 'dplyr', que puede instalarse de la siguiente manera:

[Link]("dplyr") # Esto instala el paquete 'dplyr'.


# NB. Este comando sólo necesita ser ejecutado una vez para instalar el paquete.
# Después, la librería 'dplyr' puede ser llamada usando el comando 'library'.

Podemos usar el paquete 'dplyr' para renombrar múltiples variables, como sigue:

# Primero, cambiamos los nombres de las variables en el marco de datos


'home'. library(dplyr) # Cargar paquete de biblioteca 'dplyr'
home< - rename(home, c("GF"= "HG", "GA"= "AG", "SF"= "HS", "SA"= "AS",
"STF"= "HST", "STA"= "AST", "TSRF"= "HTSR", "TSRA"= "ATSR", "PF"=
"HPts", "PA"= "APts"))

También tenemos que sustituir los elementos "H", "A" y "D" del vector Resultados
por "W", "L" y "D", lo que puede hacerse utilizando la función "recode" de "dplyr",
como se indica a continuación:

home$Resultado< - recode(home$Resultado, "H"= "W", "A"= "L", "D"=

"D") head(home)
Datos de los partidos y tablas de 109
clasificación

##
Fecha HomeTeam AwayTeam GF GA Result SF SA STF STA GD
3 12/09/2020 Liverpool Leeds 4 3 W 22 6 6 3 1
28 28/09/2020 Liverpool Arsenal 3 1 W 21 4 8 3 2
53 24/10/2020 Liverpool Sheffield United 2 1 W 17 13 5 2 1
62 31/10/2020 Liverpool West Ham 2 1 W 9 4 5 3 1
86 22/11/2020 Liverpool Leicester 3 0 W 24 11 13 4 3
106 06/12/2020 Liverpool Lobos 4 0 W 11 9 6 3 4
TG TSRF TSRA PF PA Estado
3 7 0.786 0.214 3 0 Inicio
28 4 0.840 0.160 3 0 Inicio
53 3 0.567 0.433 3 0 Inicio
62 3 0.692 0.308 3 0 Inicio
86 3 0.686 0.314 3 0 Inicio
106 4 0.550 0.450 3 0 En casa

Ahora repetimos el proceso para el marco de datos "visitante", con la única diferencia
de que tenemos que cambiar el signo de las diferencias de goles de los partidos.

away< - rename(away, c("GA"= "HG", "GF"= "AG", "SA"= "HS", "SF"= "AS",
"STA"= "HST", "STF"= "AST", "TSRA"= "HTSR", "TSRF"= "ATSR", "PA"= "HPts",
"PF"= "APts"))

away$GD< - -1*away$GD # Cambiar el signo de la diferencia de goles para reflejar el uso de "a favor"
y "en contra".

# Sustituir los elementos del vector Resultados por "W", "L", "D".
away$Result< - recode(away$Result, "H"= "L", "A"= "W", "D"= "D")

head(lejos)

##
Fecha HomeTeam AwayTeam GA GF Result SA SF STAF GD TG
15 20/09/2020 Chelsea Liverpool 0 2 W 5 18 3 6 2 2
38 04/10/2020 Aston Villa Liverpool 7 2 L 18 14 11 8 -5 9
39 17/10/2020 Everton Liverpool 2 2 D 11 22 5 8 0 4
77 08/11/2020 Man City Liverpool 1 1 D 7 10 2 3 0 2
90 28/11/2020 Brighton Liverpool 1 1 D 11 6 3 2 0 2
115 13/12/2020 Fulham Liverpool 1 1 D 10 12 5 6 0 2
TSRA TSRF PA PF Estado
15 0.217 0.783 0 3 Fuera
de
casa
38 0.562 0.438 3 0 Fuera
de
casa
39 0.333 0.667 1 1 Fuera
de
casa
77 0.412 0.588 1 1 Fuera
90 0.647 0.353 1 1 Fuera
115 0.455 0.545 1 1 Fuera
de
casa

Esto nos da exactamente lo que queríamos: un desglose completo de todos los


partidos del Liverpool, agrupados por su condición de local y visitante.

Ahora que tenemos los datos en el formato correcto, podemos producir algunas
estadísticas descriptivas para el Liverpool usando el código del Ejemplo 4.3, que
muestra la media, la mediana y la desviación estándar para las distintas métricas de
rendimiento.
110 Análisis del fútbol

EJEMPLO 4.3: PRODUCCIÓN DE ESTADÍSTICAS DESCRIPTIVAS


En este ejemplo, elaboraremos algunas estadísticas de rendimiento del Liverpool para la
temporada 2020-2021 utilizando los marcos de datos compilados en el Ejemplo 4.2.
Sin embargo, antes de hacerlo, necesitamos seleccionar qué variables queremos
incluir en el análisis. Esto se puede hacer inspeccionando los datos mediante el
comando 'names' y luego identificando las variables que son redundantes.

nombres(casa)

##
[1] "Fecha" "HomeTeam" "AwayTeam" "GF" "GA" "Resultad
o
[7] "SF" "SA" "STF" "STA" "GD" "TG
[13] "TSRF" "TSRA "PF" "PA" "Estado"

Aquí no nos interesan las variables "Date", "HomeTeam", "AwayTeam" y "Result".


Para obtener las estadísticas descriptivas de los partidos jugados en casa y fuera,
podemos utilizar el código siguiente, que utiliza la función "describeBy" del paquete
de la biblioteca "psych".

library(psych)

# Estadísticas descriptivas de los partidos jugados en casa


[Link]< - home[,c(4,5, 7:16)] # Variables seleccionadas para el análisis
estadístico [Link]< - describeBy([Link]) # Éstas son las estadísticas
descriptivas [Link]< - colSums([Link]) # Sumas de columnas
[Link]< - [Link]([Link]$n, [Link]$mean, [Link]$median, [Link]$sd, [Link])
colnames([Link])< - c("Pld", "Mean", "Median", "SD", "Total") # Renombrar variables
print(round([Link],3)) # Mostrar los estadísticos descriptivos del partido en casa

Esto produce las siguientes estadísticas descriptivas para los partidos en casa del
Liverpool:

##
Pld Media Mediana DE Total
GF 19 1.526 2.00 1.349 29.000
GA 19 1.053 1.00 1.026 20.000
SF 19 16.684 17.00 5.697 317.000
SA 19 8.316 8.00 2.868 158.000
STF 19 5.737 6.00 3.314 109.000
STA 19 3.842 4.00 1.167 73.000
GD 19 0.474 1.00 1.744 9.000
TG 19 2.579 2.00 1.644 49.000
TSRF 19 0.656 0.68 0.129 12.467
TSRA 19 0.344 0.32 0.129 6.533
PF 19 1.737 3.00 1.408 33.000
PA 19 1.105 0.00 1.370 21.000
Datos de los partidos y tablas de 111
clasificación

# Estadísticas descriptivas de los partidos fuera de casa


[Link]< - away[,c(4,5, 7:16)] # Variables seleccionadas para el análisis
estadístico [Link]< - describeBy([Link]) # Éstas son las estadísticas
descriptivas [Link]< - colSums([Link]) # Sumas de columnas
[Link]< - [Link]([Link]$n, [Link]$mean, [Link]$median, [Link]$sd, [Link])
colnames([Link])< - c("Pld", "Mean", "Median", "SD", "Total") # Renombrar variables
print(round([Link],3)) # Mostrar las estadísticas descriptivas de los partidos en casa

Esto produce las siguientes estadísticas descriptivas para los partidos del Liverpool fuera
de casa.

##
Pld Media Mediana DE Total
GA 19 1.158 1.000 1.642 22.00
GF 19 2.053 2.000 1.615 39.00
SA 19 9.211 10.000 4.090 175.00
SF 19 15.316 15.000 4.473 291.00
STA 19 3.737 3.000 2.182 71.00
STF 19 5.526 6.000 2.245 105.00
GD 19 0.895 1.000 2.401 17.00
TG 19 3.211 3.000 2.200 61.00
TSRA 19 0.371 0.364 0.128 7.05
TSRF 19 0.629 0.636 0.128 11.95
PA 19 0.789 0.000 1.084 15.00
FP 19 1.895 3.000 1.243 36.00

Para producir estadísticas descriptivas de todos los partidos (combinados de ida y vuelta)
de la temporada, basta con escribir

all< - rbind(local, visitante)


# Todas las coincidencias estadísticas descriptivas
[Link]< - all[,c(4,5, 7:16)] # Variables seleccionadas para el análisis
estadístico [Link]< - describeBy([Link]) # Éstas son las estadísticas
descriptivas [Link]< - colSums([Link]) # Sumas de columna
[Link]< - [Link]([Link]$n, [Link]$mean, [Link]$median, [Link]$sd, [Link])
colnames([Link])< - c("Pld", "Mean", "Median", "SD", "Total") # Renombrar variables
print(round([Link],3)) # Mostrar las estadísticas descriptivas del partido en casa

Lo que produce:

##
Pld Media Mediana SD Total
GF 38 1.789 2.000 1.492 68.000
GA 38 1.105 1.000 1.351 42.000
SF 38 16.000 16.000 5.099 608.000
SA 38 8.763 8.500 3.514 333.000
STF 38 5.632 6.000 2.794 214.000
STA 38 3.789 3.000 1.727 144.000
GD 38 0.684 1.000 2.081 26.000
112 Análisis del fútbol

TG 38 2.895 2.500 1.942 110.000


TSRF 38 0.643 0.667 0.127 24.417
TSRA 38 0.357 0.333 0.127 13.583
PF 38 1.816 3.000 1.312 69.000
PA 38 0.947 0.000 1.229 36.000

Aunque la metodología descrita anteriormente produce tablas que pueden ser


extremadamente informativas, pueden resultar difíciles de seguir, sobre todo si se
presenta mucha información. Por ello, a veces resulta útil elaborar gráficos a partir de
los datos, ya que suelen ser más fáciles de entender.
Los gráficos de caja pueden ser especialmente útiles a la hora de comunicar los
resultados a un público no especializado que puede no estar muy familiarizado con
los números. Para ilustrar cómo se pueden construir gráficos de caja en R,
utilizaremos el siguiente código para producir un gráfico de caja de los disparos a
puerta (SoT), tanto a favor como en contra del Liverpool durante los partidos en casa y
fuera.

# Produce un diagrama de caja de los tiros a puerta en casa y


fuera. HSTF< - home$STF # SoT para en casa
HSTA< - home$STA # SoT contra en casa ASTF<
- away$STF # SoT para fuera
ASTA< - away$STA # SoT contra away
SoT< - [Link](HSTF,HSTA,ASTF,ASTA)
boxplot(SoT, ylab= "Shots on target")

Esto produce el diagrama de caja de la Figura 4.1, que muestra que tanto en los
partidos en casa como fuera, el Liverpool hizo muchos más SoT de los que encajó.

FIGURA 4.1
Gráfico de cajas de los disparos a puerta, tanto a favor como en contra del Liverpool, durante sus
partidos en casa y fuera en la temporada 2020-2021. (HSTF= tiros a puerta en casa a favor; HSTA=
tiros a puerta en casa en contra; ASTF= tiros a puerta fuera a favor; ASTA= tiros a puerta fuera en
contra).
Datos de los partidos y tablas de 113
clasificación

A partir de los ejemplos 4.1-4.3, podemos ver que es relativamente fácil producir
en R estadísticas de rendimiento detalladas para cualquier club en cualquier
temporada directamente a partir de los datos históricos de los partidos. El código
presentado en estos ejemplos puede utilizarse y adaptarse para obtener información
más detallada sobre el rendimiento de los equipos. Por ejemplo, a partir de los
resultados del ejemplo 4.3, es interesante observar que, aunque el Liverpool recibió
más puntos por partido fuera de casa (1,895 puntos) que en casa (1,737 puntos), en
términos de TSRF y TSRA por partido, en realidad rindió mejor en casa que fuera.

4.2 Elaboración de estadísticas cara a cara a partir


de datos históricos de partidos
A menudo, cuando se trata de predecir el resultado de un partido determinado, es útil
echar un vistazo a los resultados del mismo encuentro H2H en temporadas
anteriores, ya que esto podría proporcionar información útil sobre el resultado
probable del partido [1]. Sin embargo, hacer esto a mano es un proceso lento y
tedioso, por lo que es mucho mejor dejar que R haga el trabajo duro. El ejemplo 4.4,
relativo a los partidos entre el Arsenal y el Chelsea en las cinco temporadas
comprendidas entre 2016-2017 y 2020-2021, ilustra cómo puede hacerse esto en la
práctica.

EJEMPLO 4.4: PRODUCCIÓN DE


ESTADÍSTICAS HISTÓRICAS DE PARTIDOS
CARA A CARA
Este ejemplo ilustra cómo obtener datos históricos de partidos cara a cara (H2H) del
Arsenal (equipo local) contra el Chelsea (equipo visitante) para las cinco temporadas de
2016-2017 a 2020-2021.
En primer lugar, borramos las variables y los datos existentes del espacio de trabajo.

rm(list= ls())

A continuación, descargamos los datos históricos de los partidos correspondientes a


las cinco temporadas comprendidas entre 2016-2017 y 2020-2021.

temporadas= c(rep("1617",1), rep("1718",1), rep("1819",1), rep("1920",1), rep("2021",1))


división= c(rep(c("E0"),5)) # NB. "E0" es la EPL y 5 es el número de temporadas.

urls= paste(temporadas, división, sep= "/")


urls= paste("[Link] urls, sep= "/")
114 Análisis del fútbol

Una vez especificadas las direcciones URL, utilizamos un bucle for para cargar los datos
en R y seleccionar sólo algunas variables relevantes para el análisis.

download_data= NULL
for(i en 1:longitud(urls)){
temp= [Link](urls[i])
temp= temp[,c("Div", "Date", "HomeTeam", "AwayTeam", "FTHG", "FTAG",
"FTR","HS","AS","HST","AST")]
datos_descarga= rbind(datos_descarga, temp)
}

Para comprobar que los datos se han descargado correctamente, suele ser útil
inspeccionar el marco de datos. Esto se puede hacer fácilmente utilizando las
funciones 'head' y 'tail' de R, que visualizan las filas superior e inferior del marco de
datos 'download_data'.

head(datos_descarga) # Muestra las seis primeras filas.


##
Div Fecha Equipo local Equipo visitante FTHG FTAG FTR HS AS HST AST
1 E0 13/08/16 Burnley Swansea 0 1 A 10 17 3 9
2 E0 13/08/16 Crystal Palace West Brom 0 1 A 14 13 4 3
3 E0 13/08/16 Everton Tottenham 1 1 D 12 13 6 4
4 E0 13/08/16 Hull Leicester 2 1 H 14 18 5 5
5 E0 13/08/16 Man City Sunderland 2 1 H 16 7 4 3
6 E0 13/08/16 Middlesbrough Stoke 1 1 D 12 12 2 1

tail(datos_descarga) # Muestra las seis últimas filas.

##
Div Fecha Equipo local Equipo visitante FTHG FTAG FTR HS AS
1895 E0 23/05/2021 Leicester Tottenham 2 4 A 10 11
1896 E0 23/05/2021 Liverpool Crystal Palace 2 0 H 19 5
1897 E0 23/05/2021 Man City Everton 5 0 H 21 8
1898 E0 23/05/2021 Sheffield United Burnley 1 0 H 12 10
1899 E0 23/05/2021 West Ham Southampton 3 0 H 14 17
1900 E0 23/05/2021 Wolves Man United 1 2 A 14 9
HST AST
1895 6 4
1896 5 4
1897 11 3
1898 3 3
1899 7 5
1900 4 4

Ahora que el conjunto de datos de partidos históricos se ha cargado de forma segura


en R, podemos proceder a buscar nuestros partidos H2H, que en este ejemplo
implican al Arsenal y al Chelsea.

teamH< - "Arsenal" # Este es el equipo local. teamA<


- "Chelsea" # Este es el equipo visitante.
Datos de los partidos y tablas de 115
clasificación

Los partidos del Arsenal contra el Chelsea se pueden extraer del marco de datos de
varias formas, pero aquí utilizaremos una variable indicadora para hacer el trabajo.
Crear una variable indicadora es un truco útil que puede ser útil en muchas
aplicaciones. En este caso, primero creamos un nuevo vector indicador, que
inicialmente se rellena completamente con ceros.

n< - nrow(download_data) # Esto determina la longitud del vector indicador. ind< -


matrix(0,n,1) # Esto creó una matriz [n,1] (vector) poblada con ceros.

A continuación, unimos este nuevo vector al marco de datos existente y le


damos el nombre de 'ndat'.

ndat< - [Link](datos_descarga, ind)

Ahora rellenamos la variable indicadora utilizando un bucle for y una sentencia if.
Aquí también introduciremos el operador AND '&' que toma dos valores lógicos y
devuelve TRUE sólo si ambos valores son TRUE.

for (i en 1:n){
if(ndat$HomeTeam[i]== teamH & ndat$AwayTeam[i]== teamA){ndat$ind[i]< - 1}
}

Esto inserta 1 en la variable indicadora cuando se cumplen los criterios de la prueba


(es decir, el equipo local es el Arsenal y el equipo visitante es el Chelsea). Una vez
hecho esto, podemos seleccionar sólo los partidos para los que la variable indicadora
es 1 utilizando el código siguiente:

H2H< - ndat[ndat$ind== 1,]

Para completar la información, añadiremos también los porcentajes de disparos de los


respectivos partidos.

H2H["HTSR"]< - NA # Esto crea la nueva columna para almacenar el ratio de tiros del
equipo local. H2H["ATSR"]< - NA # Esto crea la nueva columna para almacenar el ratio de
tiros del equipo visitante. H2H$HTSR< - round(H2H$HS/(H2H$HS+ H2H$AS),3) # Aquí
redondeamos a 3 dp H2H$ATSR< - round(H2H$AS/(H2H$AS+ H2H$HS),3) # Aquí
redondeamos a 3 dp

Por último, mostramos los resultados de los partidos H2H.

print(H2H)
116 Análisis del fútbol

##
Div Fecha Equipo local Equipo visitante FTHG FTAG FTR HS AS HST AST ind
51 E0 24/09/16 Arsenal Chelsea 3 0 H 14 9 5 2 1
599 E0 03/01/2018 Arsenal Chelsea 2 2 D 14 19 6 6 1
981 E0 19/01/2019 Arsenal Chelsea 2 0 H 13 13 5 1 1
1337 E0 29/12/2019 Arsenal Chelsea 1 2 A 7 13 2 4 1
1661 E0 26/12/2020 Arsenal Chelsea 3 1 H 15 19 7 3 1
HTSR ATSR
51 0.609 0.391
599 0.424 0.576
981 0.500 0.500
1337 0.350 0.650
1661 0.441 0.559

A partir de esto, podemos ver que el Arsenal ganó tres de los partidos H2H anteriores,
y que el Chelsea sólo ganó uno. También hubo un empate.

4.3 Elaboración de tablas de clasificación PiT a partir de datos históricos


de partidos
A menudo, cuando se analiza el rendimiento de los equipos utilizando datos
históricos, es útil conocer la posición en la tabla de clasificación de los distintos
clubes en un momento dado. Esto puede ser muy útil a la hora de analizar el
rendimiento de un equipo a lo largo de toda una temporada. Desgraciadamente,
obtener los datos históricos de la posición en la liga puede ser una tarea larga y
tediosa si se hace a mano. Así que, una vez más, es mucho mejor dejar que R haga
todo el trabajo duro. El ejemplo 4.5 ilustra cómo se pueden construir
retrospectivamente tablas de clasificación puntuales a partir de datos históricos de
partidos utilizando una función adaptada de la original, que se puede encontrar en
[Link] 18 [2].

EJEMPLO 4.5: ELABORACIÓN DE TABLAS DE LIGA PiT A


PARTIR DE DATOS HISTÓRICOS DE PARTIDOS
En este ejemplo, vamos a utilizar datos históricos de partidos para construir la tabla de
clasificación de la liga EPL tras 98 partidos de la temporada 2020-2021, que era la
tabla a 30 de noviembre de 2020 tras aproximadamente diez jornadas de competición.
Para ello, utilizaremos las dos funciones definidas por el usuario que se describen a
continuación. (NB. Para más información sobre las funciones definidas por el
usuario, véase el Cuadro de conceptos clave 4.1.)
En primer lugar, borraremos todas las variables y datos existentes en el espacio de
trabajo.

rm(list= ls()) # Borra todas las variables del espacio de trabajo


Datos de los partidos y tablas de 117
clasificación

Ahora cargamos los datos históricos de los partidos desde [Link]


[Link]/ [Link]. En este caso, utilizaremos sólo los 98 primeros partidos de la
EPL y las siete primeras variables, pero por supuesto se puede seleccionar cualquier
liga y número de partidos para construir una tabla de clasificación PiT apropiada.

PiT_dat< - head([Link]('[Link]

NOTA. '98 partidos' incluye los partidos del 30 de noviembre de 2020 y equivale
aproximadamente a 10 rondas de competición.
Inspeccionemos los datos descargados.

names(PiT_dat)

##
[1] "Div" "Fecha" "Hora" "HomeTeam" "AwayTeam" "FTHG" "HomeTeam"
"AwayTeam" "FTHG" "FTAG

Para utilizar las funciones definidas por el usuario que se describen a continuación, es
necesario crear primero cuatro vectores, "HomeTeam", "AwayTeam", "HomeGoals" y
"AwayGoals", que se cargarán en la función "[Link]".

# Define las cuatro variables que se cargarán en la función definida por el usuario.
HomeTeam< - PiT_dat$HomeTeam
AwayTeam< - PiT_dat$AwayTeam
HomeGoals< - PiT_dat$FTHG
AwayGoals< - PiT_dat$FTAG

Para producir una tabla de clasificación PiT, es necesario crear dos funciones
definidas por el usuario: 'resultado' y '[Link]'. La primera de estas funciones
determina el resultado del partido (es decir, H, D o A) basándose en los goles
marcados por los equipos local y visitante, mientras que la segunda produce una tabla
de clasificación PiT basada en los resultados de los partidos. Es importante destacar
que la función "[Link]" utiliza la función "resultado", por lo que sólo es
necesario aplicar la función "[Link]" cuando se construye una tabla de
clasificación PiT.

# Función 1. (Esto crea un vector de resultados de coincidencias.)

outcome< - function(hGoals, aGoals){


nMatches< - length(hGoals)
resultados< - matrix(NA,nMatches,1) # Crea un vector vacío para almacenar los resultados de las
coincidencias.

# Esto rellena el vector de resultados con los resultados de las coincidencias


(es decir, H, A o D) for(i in 1:nMatches){
if(hPropuestas[i]> aPropuestas[i]){resultados[i]< - "H"}
118 Análisis del fútbol

if(hPreguntas[i]< aPreguntas[i]){resultados[i]< - "A"}


if(hMetas[i]== aMetas[i]){resultados[i]< - "D"}
}
return(resultados)
}

# Función 2. (Crea una tabla de clasificación actual a partir de los datos de resultados

de los partidos.) [Link]< - function(hTeam, aTeam, hGoals, aGoals){

# Recoge los nombres de los equipos y compáralos en un vector


[Link]< - unique(hEquipo)
(equipos< - sort([Link])) # Ordenar por orden alfabético.
nEquipos= length(equipos) # Esto identifica el número de equipos en la liga.

# Crear un vector que contenga los resultados de los partidos (es decir, H,
A o D) resultados< - outcome(hGoals, aGoals)

# Crear vectores vacíos para almacenar


los resultados. x< - numeric(nEquipos)
hGanadores< - x; hPerdedores< - x;
hRemates< - x; aGanadores< - x;
aPerdedores< - x; aRemates< - x;
[Link]< - x; [Link]< - x; [Link]< - x;
[Link]< - x; pts< - x;

# Rellenar vectores
for (i in 1:nEquipos) {
hResultados< - resultados[hEquipo== equipos[i]]
aResultados< - resultados[aEquipo== equipos[i]]
[Link][i]< - length(hResults)+ length(aResults) goals.H< -
sum(hGoals[hEquipo== equipos[i]])
goals.A< - sum(aGoals[aEquipo== equipos[i]])
[Link][i]< - goals.H+ goals.A
concedido.H< - suma(aGoles[hEquipo==
equipos[i]]) concedido.A< - suma(hGoles[aEquipo==
equipos[i]]) [Link] contra[i]< - concedido.H+
concedido.A [Link][i]< - goles.a favor[i] - [Link]
contra[i] hGanancias[i]< - suma(hResultados== "H")
hRemates[i]< - suma(hResultados== "D")
hPérdidas[i]< - suma(hResultados== "A")
aGanancias[i]< - suma(aResultados==
"A") aRemates[i]< - suma(aResultados==
"D") aPérdidas[i]< - suma(aResultados==
"H")

# Calcula el total de puntos a partir del número de victorias y empates de los respectivos equipos.

# Puntos otorgados por los resultados del partido


[Link]< - 3
[Link]< - 1
pts[i]< - ([Link]*(hWins[i]+ aWins[i]))+ ([Link] * (hDraws[i]+ aDraws[i]))
}

tabla< - [Link](cbind([Link], hWins, hDraws,hLoss, aWins, aDraws, aLoss, [Link],


[Link], [Link], pts), [Link]= teams)

names(tabla)< - c("PLD", "HW", "HD", "HL", "AW", "AD", "AL", "GF", "GA", "GD", "PTS")
ord< - order(-table$PTS, -table$GD, -table$GF)
table< - table[ord, ]
return(tabla)
}
Datos de los partidos y tablas de 119
clasificación

NB. Las funciones "resultado" y "[Link]" mencionadas anteriormente son una


adaptación del código presentado en [Link] [2].
Una vez escritas las funciones definidas por el usuario, ya podemos
aplicarlas para producir la tabla de clasificación PiT, como se indica a
continuación.

[Link]< - [Link](EquipoInicial, EquipoExtrajero, GolesIniciales, GolesExtrajeros)


print([Link])

Esto produce:

##
PLD HW HD HL AW AD AL GF GA GD PTS
Tottenham 10 2 2 1 4 1 0 21 9 12 21
Liverpool 10 5 0 0 1 3 1 22 17 5 21
Chelsea 10 2 2 1 3 2 0 22 10 12 19
Leicester 10 2 0 3 4 0 1 19 14 5 18
West Ham 10 3 1 1 2 1 2 17 11 6 17
Southampton 10 3 0 2 2 2 1 19 16 3 17
Lobos 10 2 2 1 3 0 2 11 11 0 17
Everton 10 2 1 2 3 0 2 19 17 2 16
Man United 9 1 1 3 4 0 0 16 16 0 16
Aston Villa 9 2 0 3 3 0 1 20 13 7 15
Manchester City 9 2 1 1 2 2 1 15 11 4 15
Leeds 10 1 2 2 3 0 2 15 17 -2 14
Newcastle 10 2 0 3 2 2 1 12 15 -3 14
Arsenal 10 2 0 3 2 1 2 10 12 -2 13
Palacio de 10 2 1 2 2 0 3 12 15 -3 13
Cristal
Brighton 10 0 3 2 2 1 2 14 16 -2 10
Fulham 10 1 0 4 1 1 3 11 19 -8 7
West Brom 10 1 2 2 0 1 4 7 18 -11 6
Burnley 9 1 0 3 0 2 3 4 17 -13 5
Sheffield United 10 0 1 4 0 0 5 4 16 -12 1

A partir de esto, podemos ver que después de aproximadamente 10 rondas de


competición, el Tottenham lideraba la EPL, con el Liverpool segundo. Sin embargo,
no fue así como apareció la tabla final al final de la temporada (EoS), porque el
Manchester City ganó realmente la EPL en la temporada 2020-2021, con el
Liverpool terminando tercero y el Tottenham séptimo.
120 Análisis del fútbol

CONCEPTO CLAVE CUADRO 4.1:


ESCRIBIR UNA FUNCIÓN DEFINIDA
POR EL USUARIO EN R
En R, una función definida por el usuario es un algoritmo personalizado
creado por el usuario para realizar una tarea específica. Por lo general, se crean
para realizar tareas o cálculos complejos para los que no existe una función
incorporada en R. Un ejemplo de función definida por el usuario en este
capítulo es "[Link]", que, como su nombre indica, crea una tabla de la
liga de fútbol en un momento dado a partir de datos históricos de partidos, una
tarea muy específica y que la mayoría de la gente no suele utilizar en su vida
cotidiana.
Al crear una función definida por el usuario, primero tenemos que definir la
función utilizando el comando 'function', seguido de todos los argumentos que
utilizará la función y las operaciones que realizará. Por ejemplo, podríamos
crear una simple función definida por el usuario para calcular el área de un
rectángulo utilizando el siguiente código:

# Crear una función llamada 'calc_rectangle_area'


calc_rectangle_area <- function(longitud, anchura) {
área <- longitud *
anchura return(área)
}

Esta función, que se llama 'calc_rectangle_area', utiliza dos argumentos, 'longitud'


y 'anchura', para calcular el área de un rectángulo, que devuelve como salida. Con
las funciones definidas por el usuario, todos los argumentos de entrada (es decir,
las variables y valores de entrada) deben declararse entre paréntesis directamente
después del término 'function'. La parte entre llaves {...} es donde el usuario le
dice a R qué hacer cuando se llama a la función. En este caso, le hemos dicho a R
que calcule el área de un rectángulo multiplicando su longitud y anchura, y que
devuelva el área calculada como salida.
Para utilizar la función 'calc-rectangle-area' en la práctica, simplemente
escribimos el siguiente código, que introduce dos parámetros, 'length= 5' y
'width= 3'.

# Especifique los
valores de entrada
longitud <- 5
anchura <- 3

# Aplicar la función
calc_rectangle_area(longitud,anchur
a)

La función devuelve la siguiente salida:

## [1] 15
Datos de los partidos y tablas de 121
clasificación

Por supuesto, las funciones definidas por el usuario suelen ser mucho más
complejas que el sencillo ejemplo que mostramos aquí, pero el principio
general sigue siendo el mismo. Escribimos un algoritmo para realizar una
tarea específica, y luego lo llamamos cada vez que deseamos utilizarlo. Como
resultado, las funciones definidas por el usuario son particularmente populares
cuando se realizan tareas complejas que deben repetirse varias veces.

4.4 Recopilación de tablas de características PiT a partir de datos históricos de


partidos
En el aprendizaje automático, el término "rasgo" se utiliza a menudo para referirse a
una propiedad o característica individual mensurable que puede utilizarse con fines
predictivos. Por ejemplo, los ratios de tiros totales del equipo local y visitante (HTSR
y ATSR) son características que pueden utilizarse tanto para evaluar el rendimiento
pasado como para predecir el rendimiento futuro. En el ejemplo 4.3, ya hemos visto
cómo podemos combinar estas características para un solo club durante toda una
temporada. Sin embargo, a la hora de hacer predicciones, a menudo resulta útil
compilar tablas de características para todos los equipos de la liga en momentos
concretos. Para ello, se necesita una función definida por el usuario que se pueda
aplicar a todos los equipos de la liga, como se ilustra en el Ejemplo 4.6. Esta función
(denominada aquí "[Link]") es una adaptación de un algoritmo de Tropiano [3]
y suma las distintas métricas de rendimiento de los partidos individuales para
producir un conjunto de puntuaciones de características PiT que pueden utilizarse
para evaluar el rendimiento relativo de cada uno de los equipos de la liga.

EJEMPLO 4.6: ELABORACIÓN DE TABLAS DE


CARACTERÍSTICAS DE PiT A PARTIR DE LOS
DATOS HISTÓRICOS DE LOS PARTIDOS
En este ejemplo, vamos a utilizar datos históricos de partidos para construir una tabla
de características tras 98 partidos de la temporada 2020-2021, lo que equivale
aproximadamente a diez jornadas de competición. Para ello utilizaremos la función
definida por el usuario que se describe a continuación.
De nuevo, primero limpiaremos el espacio de trabajo.

rm(lista= ls()) # Borra todas las variables del espacio de trabajo

Ahora cargamos en R los datos de los partidos de la temporada 2020-2021,


seleccionando sólo las 20 primeras variables y los 98 primeros partidos.

fb_data< - head([Link]('[Link]
122 Análisis del fútbol

NB. Se trata de los mismos datos que hemos utilizado en los ejemplos anteriores, pero
aquí incluimos las siguientes variables adicionales:

• HC= Rincones del equipo local


• AC= Rincones del equipo visitante

A continuación, seleccionamos las variables que queremos mantener en el análisis.

soc_dat< - fb_data[,c("Date", "HomeTeam", "AwayTeam", "FTHG", "FTAG",


"FTR","HS","AS","HST","AST","HC","AC")]

A continuación, añadimos algunas nuevas variables derivadas:

soc_dat["HPts"]< - 0 # Esto crea la nueva columna para almacenar los puntos del equipo local por partido
soc_dat["APts"]< - 0 # Esto crea la nueva columna para almacenar los puntos del equipo visitante por
partido

Que rellenamos de la siguiente manera

for(i en 1:nrow(soc_dat)){
if(soc_dat$FTR[i]== "H"){soc_dat$HPts[i]< - 3}
if(soc_dat$FTR[i]== "A"){soc_dat$APts[i]< - 3}
if(soc_dat$FTR[i]== "D") {soc_dat$HPts[i]< - 1}
if(soc_dat$FTR[i]== "D") {soc_dat$APts[i]< - 1}
}

# Renombra los nombres de las columnas


colnames(soc_dat)[colnames(soc_dat)== 'FTHG']< - 'HG'
colnames(soc_dat)[colnames(soc_dat)== 'FTAG']< - 'AG'
colnames(soc_dat)[colnames(soc_dat)== 'FTR']< - 'Result'

Para inspeccionar el marco de datos resultante, utilizamos la función 'head'.

head(soc_dat)

##
Fecha Equipo local Equipo visitante HG AG Resultado HS AS HST AST HC AC
1 12/09/2020 Fulham Arsenal 0 3 A 5 13 2 6 2 3
2 12/09/2020 Crystal Palace Southampton 1 0 H 5 9 3 5 7 3
3 12/09/2020 Liverpool Leeds 4 3 H 22 6 6 3 9 0
4 12/09/2020 West Ham Newcastle 0 2 A 15 15 3 2 8 7
5 13/09/2020 West Brom Leicester 0 3 A 7 13 1 7 2 5
6 13/09/2020 Tottenham Everton 0 1 A 9 15 5 4 5 3
HPts APts
1 0 3
Datos de los partidos y tablas de 123
clasificación

2 3 0
3 3 0
4 0 3
5 0 3
6 0 3

Una vez cargados los primeros 98 partidos en R, podemos aplicar la siguiente


función definida por el usuario, '[Link]', para calcular las puntuaciones PiT de
cualquier equipo. Aquí la aplicamos al Tottenham, que tras 10 jornadas de
competición lideraba la EPL en 2020, y al Manchester City, que terminó en cabeza al
final de la temporada.

# '[Link]' function
[Link]< - function(df, team){
Hmatches< - df[df$HomeTeam== team,] # Selecciona los partidos en casa del equipo objetivo.
Amatches< - df[df$AwayTeam== team,] # Selecciona los partidos fuera de casa del equipo
objetivo. all< - [Link](Hmatches,Amatches)
n< - nrow(all) # Número de partidos
# Crear vectores vacíos para almacenar
los resultados. x< - numeric(n)
GF< - x; GA< - x; SF< - x; SA< - x; STF< - x; STA< - x; CF< -
x; CA< - x; Pts< - x;

# Calcula el total de goles for(i


en 1:n){
if(all$HomeTeam[i]== team){GF[i]< - all$HG[i]}
else {GF[i]< - all$AG[i]}
}

# Calcula el total de goles en


contra for(i en 1:n){
if(all$HomeTeam[i]== team){GA[i]< - all$AG[i]}
else {GA[i]< - all$HG[i]}
}

# Calcula el total de tiros for


for(i en 1:n){
if(all$HomeTeam[i]== team){SF[i]< - all$HS[i]} else
{SF[i]< - all$AS[i]}
}

# Calcula el total de tiros en contra


for(i en 1:n){
if(all$HomeTeam[i]== team){SA[i]< - all$AS[i]} else
{SA[i]< - all$HS[i]}
}

# Calcula el total de tiros a puerta for(i en


1:n){
if(all$HomeTeam[i]== team){STF[i]< - all$HST[i]} else
{STF[i]< - all$AST[i]}
}

# Calcula el total de tiros a puerta en contra


for(i en 1:n){
if(all$HomeTeam[i]== team){STA[i]< - all$AST[i]} else
{STA[i]< - all$HST[i]}
}
124 Análisis del fútbol

# Calcula el total de esquinas for


for(i en 1:n){
if(all$HomeTeam[i]== team){CF[i]< - all$HC[i]} else
{CF[i]< - all$AC[i]}
}

# Calcula el total de córners en contra


para(i en 1:n){
if(all$HomeTeam[i]== team){CA[i]< - all$AC[i]} else
{CA[i]< - all$HC[i]}
}

# Calcula el total de puntos


adjudicados for(i en 1:n){
if(all$HomeTeam[i]== team){Pts[i]< - all$HPts[i]} else
{Pts[i]< - all$APts[i]}
}
Pld< - matrix(1,n,1) # Vector que contiene los partidos jugados
GD< - GF-GA # Calcula la diferencia de goles
TG< - GF+ GA # Calcula el total de goles
TSRF< - SF/(SF+ SA) # Calcula la proporción total de tiros a
favor TSRA< - SA/(SF+ SA) # Calcula la proporción total de
tiros en contra

feats< - [Link](Pld,GF,GA,GD,TG,SF,SA,STF,STA,TSRF,TSRA,CF,CA,Pts)
featsSums< - colSums(feats)
featsRes< - featsSums
nOb< - nrow(feats)
featsRes[10]< - featsSums[10]/nOb # Esto calcula el TSRF medio. featsRes[11]< -
featsSums[11]/nOb # Esto calcula el TSRA medio. return(round(featsRes,2))
}

Ahora podemos aplicar la función '[Link]' al Tottenham y al Manchester City.

[Link]< - [Link](soc_dat, "Tottenham") print([Link])

##
Pld GF GA GD TG SF SA STF STA TSRF
10.00 21.00 9.00 12.00 30.00 120.00 119.00 51.00 34.00 0.49
TSRA CF CA Pts
0.51 42.00 50.00 21.00

[Link]< - [Link](soc_dat, "Man City") print([Link])

##
Pld GF GA GD TG SF SA STF STA TSRF
9.00 15.00 11.00 4.00 26.00 144.00 74.00 49.00 27.00 0.65
TSRA CF CA Pts
0.35 57.00 31.00 15.00
Datos de los partidos y tablas de 125
clasificación

NB. A excepción de TSRF y TSRA, que son valores medios, las puntuaciones de las
características que se indican aquí son las sumas de las distintas métricas adquiridas en
cada partido.
Los resultados del Tottenham, líder de la liga en aquel momento, son muy
interesantes. Aunque muestran que el Tottenham exhibía una saludable diferencia
positiva de goles de 12 después de 10 partidos, los resultados TSR sugieren que el
equipo podría no haber estado jugando tan bien. A diferencia del Manchester City y
de muchos de sus competidores (véase más adelante), la puntuación media TSRA
del Tottenham, de 0,51, fue en realidad mayor que su puntuación media TSRF, que
fue de 0,49, lo que implica que en la mayoría de los partidos recibió más disparos de
los que realizó. Esto sugiere que posiblemente tuvieron suerte de liderar la liga tras
la 10ª jornada. En comparación, el Manchester City, después de nueve partidos, tenía
una puntuación TSRF media (0,65) mucho mayor que su puntuación TSRA (0,35), lo
que implica que quizá debería haber sumado más puntos en esa fase de la
competición. Por lo tanto, no es de extrañar que el rendimiento del Tottenham
decayera a medida que avanzaba la temporada, terminando finalmente en séptimo
lugar, mientras que el Manchester City mejoró constantemente y terminó en lo más
alto de la EPL en la temporada 2020-2021.
El siguiente código muestra cómo se puede aplicar la función '[Link]' a todos
los equipos de la EPL.
En primer lugar, identificamos los nombres de los equipos de la liga y los
cotejamos en un vector.

Equipos< - unique(soc_dat$HomeTeam)
Equipos< - sort(Equipos) # Ordenarlos alfabéticamente
nEquipos< - length(Equipos) # Número de equipos
print(Equipos)

##
[1] "Arsenal" "Aston Villa" "Brighton"
[4] "Burnley" "Chelsea" "Crystal Palace"
[7] "Everton" "Fulham" "Leeds"
[10] "Leicester" "Liverpool" "Man City"
[13] "Man United "Newcastle" "Sheffield United"
[16] "Southampton" "Tottenham" "West Brom"
[19] "West Ham" "Wolves"

Ahora podemos aplicar la función '[Link]' a todos los equipos de la liga


utilizando un 'bucle for'.
126 Análisis del fútbol

featureRes< - matrix(NA,nEquipos,14)
for(i in 1:nEquipos){
featureRes[i,]< - [Link](soc_dat, Equipos[i])
}

# Compilar los resultados de la tabla de características


featureTab< - [Link](Equipos, featureRes)
colnames(featureTab)< - c("Equipo", "Pld", "GF", "GA", "GD", "TG", "SF", "SA", "STF",
"STA","TSRF","TSRA","CF","CA","Pts")
print(featureTab)

Esto produce:

##
Equipo Pld GF GA GD TG SF SA STF STA TSRF TSRA CF CA Pts
1 Arsenal 10 10 12 -2 22 95 124 32 39 0.46 0.54 47 50 13
2 Aston Villa 9 20 13 7 33 135 107 52 37 0.58 0.42 66 33 15
3 Brighton 10 14 16 -2 30 123 78 34 28 0.60 0.40 50 40 10
4 Burnley 9 4 17 -13 21 83 118 24 44 0.42 0.58 36 55 5
5 Chelsea 10 22 10 12 32 132 95 54 27 0.58 0.42 50 54 19
6 Palacio de Cristal 10 12 15 -3 27 94 133 36 45 0.40 0.60 51 55 13
7 Everton 10 19 17 2 36 116 129 49 49 0.48 0.52 48 43 16
8 Fulham 10 11 19 -8 30 126 124 42 57 0.50 0.50 38 45 7
9 Leeds 10 15 17 -2 32 153 136 55 49 0.52 0.48 55 49 14
10 Leicester 10 19 14 5 33 102 127 45 49 0.45 0.55 53 57 18
11 Liverpool 10 22 17 5 39 163 90 64 39 0.64 0.36 62 21 21
12 Ciudad 9 15 11 4 26 144 74 49 27 0.65 0.35 57 31 15
13 Manchester United 9 16 16 0 32 120 98 47 33 0.55 0.45 53 35 16
14 Newcastle 10 12 15 -3 27 86 158 28 59 0.36 0.64 42 55 14
15 Sheffield United 10 4 16 -12 20 97 152 31 57 0.38 0.62 50 67 1
16 Southampton 10 19 16 3 35 107 104 51 47 0.53 0.47 37 59 17
17 Tottenham 10 21 9 12 30 120 119 51 34 0.49 0.51 42 50 21
18 West Brom 10 7 18 -11 25 95 149 30 61 0.40 0.60 44 66 6
19 West Ham 10 17 11 6 28 118 109 40 39 0.51 0.49 47 51 17
20 Lobos 10 11 11 0 22 122 107 39 33 0.53 0.47 44 56 17

En el ejemplo 4.6, hemos visto cómo se puede utilizar R para producir una serie de
puntuaciones de las características de los equipos en las ligas. Pero, ¿cómo se
pueden utilizar para evaluar el rendimiento de los equipos? Bien, un método sencillo
es producir un gráfico de dispersión de los puntos ganados y las características
seleccionadas, como se ilustra en el ejemplo 4.7. Esto nos permite visualizar el
rendimiento de los equipos. Esto nos permite visualizar el rendimiento de los
respectivos equipos con respecto a un atributo. Una métrica utilizada con frecuencia
para evaluar el rendimiento de un equipo es el TSR (es decir, TSRF), que combina
las cualidades ofensivas y defensivas en una única puntuación [4]. Como tal, capta
uno de los atributos clave (es decir, la proporción de tiros realizados frente a los
recibidos) que puede influir en gran medida en el resultado de los partidos (para más
detalles, véase el capítulo 5). El Ejemplo 4.7, que utiliza el marco de datos
'featureTab' para los 98 partidos producidos en el Ejemplo 4.6, ilustra cómo puede
hacerse esto.
Datos de los partidos y tablas de 127
clasificación

EJEMPLO 4.7: ELABORACIÓN DE UN GRÁFICO DE DISPERSIÓN DE


CARACTERÍSTICAS TSR
Aquí utilizamos el marco de datos 'featureTab' del Ejemplo 4.6 que se produjo
después de 98 partidos en la temporada 2020-2021, para producir un gráfico de
dispersión de TSRF y puntos ganados para todos los equipos de la EPL.

# Gráfico de dispersión de TSRF y puntos


ganados x< - featureTab$TSRF
y< - featureTab$Pts

Antes de crear el gráfico de dispersión, utilizamos la función "[Link]" para calcular el


valor r de la correlación de Pearson para la relación entre el TSRF y los puntos
obtenidos.

# Correlación entre el TSRF y los puntos obtenidos


[Link](x,y)

Esto produce la siguiente salida, de la que podemos ver que r= 0.513 y que la relación
es significativa, con p= 0.021.

## Correlación producto-momento de Pearson

datos: x e y
t= 2.5353, df= 18, p-valor= 0.02073
hipótesis alternativa: la correlación verdadera no es igual a 0
intervalo de confianza del 95 por ciento:
0,09113012 0,77871828
estimaciones muestrales:
cor
0.5129646

# Gráfico de dispersión
plot(x,y, pch= 20, xlim= c(0.2,0.8), ylim= c(0,25), xlab= "Average TSRF score", ylab= "Points earned") text(y~x,
labels= Teams, cex= 0.8, font= 1, pos= 4) # Esto pone los nombres de los equipos en los puntos de datos.
abline(lm(y~x), lty= 2) # Esto dibuja una línea de mínimos cuadrados de mejor ajuste a través de los puntos
de datos.

El gráfico de dispersión resultante se muestra en la Figura 4.2.


128 Análisis del fútbol

FIGURA 4.2
Gráfico de dispersión de la puntuación media del ratio total de disparos a puerta (TSRF) y los puntos
obtenidos por los equipos de la EPL (temporada 2020-2021) tras 98 partidos (es decir,
aproximadamente 10 rondas de competición).

En la figura 4.2 se puede observar que, tras 98 partidos, existe una correlación
razonable (r= 0.513) entre el TSRF y los puntos ganados, con la mayoría de los equipos
agrupados cerca de la línea de mejor ajuste, a pesar de que algunos sólo habían
jugado 9 partidos en lugar de 10. Sin embargo, cinco equipos (tres de los cuales,
Sheffield United, West Bromwich y Fulham, descendieron posteriormente) se sitúan
muy por debajo de la línea de mejor ajuste, lo que indica que por alguna razón estos
equipos no conseguían convertir su TSRF en puntos de liga. Por ejemplo,
consideremos al Tottenham, que terminó la temporada en 7ª posición con 62 puntos,
y al Fulham, que quedó 18º y descendió con un total de sólo 28 puntos. Después de
10 partidos, el Tottenham tenía una puntuación TSRF de 0,49 y un total de 21
puntos, mientras que el Fulham tenía una puntuación TSRF ligeramente mejor, de
0,50, pero sólo había acumulado 7 puntos. Esto sugiere que la calidad de los disparos
del Tottenham (SoT= 51) fue en general mejor que la del Fulham (SoT= 42).
Además, el Tottenham encajó muchos menos SoT (34) que el Fulham (57). Así pues,
aunque las puntuaciones TSRF del Tottenham y el Fulham fueron similares, es
probable que los dos equipos difirieran mucho en la calidad de su juego, de ahí la
diferencia de 14 puntos entre los dos equipos después de 10 partidos. A pesar de
ello, en la figura 4.2 se aprecia que el Tottenham se sitúa a cierta distancia por
encima de la línea de mejor ajuste, lo que quizá sugiere que la buena suerte pudo
influir en algunas de sus actuaciones en los primeros partidos de la temporada, ya
que no fueron capaces de mantener el mismo ímpetu a medida que avanzaba la
temporada.
Si comparamos la Figura 4.2 con la Figura 4.3, que representa la posición de la
EoS, se puede observar que la correlación entre TSRF y puntos ganados se ha
reforzado (r= 0.731) y que todos menos Brighton y Fulham se sitúan relativamente
cerca de la línea de mejor ajuste. Esto sugiere que mientras estos dos equipos
Datos de los partidos y tablas de 129
clasificación

creaban ocasiones de gol, sus disparos no se convertían en goles. También llama la


atención que dos de los equipos descendidos, Sheffield United y West Bromwich,
tuvieran las puntuaciones TSRF más bajas de la liga, lo que indica que no creaban
muchas ocasiones de gol.

FIGURA 4.3
Gráfico de dispersión de la puntuación media del ratio total de disparos a puerta (TSRF) y los puntos
obtenidos por los equipos de la EPL (temporada 2020-2021) después de 380 partidos (es decir, al final
de la temporada).

Referencias
1. Chamberlain M: Predicciones de fútbol basadas en datos: Construyendo la
estrategia perfecta de apuestas de más de 2,5 goles para la Premier League inglesa.
Publicación independiente; [Link]; 2019.
2. [Link]: Funciones en R para tablas de liga de fútbol y matriz de
resultados. En: opis- thokontanet. vol. [Link] 18; 2012.
3. Tropiano A: Codifica un modelo de apuestas de fútbol en un fin de semana.
Publicación independiente; 2020.
4. Joslyn LR, Joslyn NJ, Joslyn MR: ¿Qué proporciona una temporada mejorada en el
fútbol universitario masculino? The relative effects of shots, attacking and
defending scoring efficiency on year-to-year change in season win percentage. The
Sport Journal 29 de junio de 2017:1-11.

También podría gustarte