Una mirada al Soccer Analytics usando R — Parte II

En este post seguiré con la descripción de las categorías propuestas para enmarcar los tipos de análisis que comúnmente se realizan en el campo del Soccer Analytics. Al igual que la vez anterior (el post previo aquí) también incluiré un ejemplo en R.

Ahora es el turno de la categoría N°2: Modelos de probabilidades, cuyo objetivo general es estudiar/modelar las probabilidades de resultados de partidos (o etapas de torneos) conociendo previamente los valores de variables específicas de los equipos y/o jugadores analizados.

Algunos casos típicos son la estimación de probabilidades de:

  • Resultados globales: Gana Local / Empate / Gana Visita
  • Convertir X goles en un partido
  • Clasificar a un torneo o avanzar de fase dentro de un torneo
  • Posiciones en una liga

Hay algunos blogs dedicados a publicar este tipo de análisis y dar seguimiento a sus resultados. Uno de los más famosos es FiveThirtyEight, quienes desarrollaron un indicador propio (SPI rating) y mantienen actualizado sus modelos para las principales ligas y copas europeas, la MLS, entre otras. A continuación un pantallazo a modo de ejemplo:

Fuente: FiveThirtyEight

En el contexto de mi proyecto Dato Fútbol también he realizado algunos análisis de este tipo que si gustas puedes revisar: Copa del Mundo Rusia 2018 (resultados y seguimiento en este hilo de Twitter), Copa Libertadores 2018, Clasificatorias Conmebol.

Las variables consideradas en la mayoría de estas aplicaciones son:

  • Algún tipo de ranking, como por ejemplo ELO o FIFA
  • Valorización económica del plantel en el mercado
  • Porcentaje de jugadores respecto al total del plantel que juega en las principales ligas europeas
  • Odds de casas de apuestas
  • Algún tipo de característica de los jugadores involucrados

Para conseguir estos datos es posible hacerlo desde algunos repositorios publicos como Kaggle o Github, o bien hacer algo de web scraping desde casas de apuestas o sitios específicos como Transfermarkt.

Es común que se apliquen métodos como regresión logística (binomial) o de Poisson (distribución de goles), o cualquier otro algoritmo de machine learning para problemas de clasificación enfocados en variables dicotómicas (SI/NO).


Ejemplo en R

  • Contexto

Repetiré el análisis que hice para la fase de grupos de la Copa Libertadores 2018 ahora para la edición 2019 con el objetivo de estimar las probabilidades de cada equipo de avanzar a la siguiente fase (octavos de final).

Para ello considero los datos históricos (desde 2011) del rendimiento de los equipos participantes y su respectivo valor económico del plantel en el mercado, en millones de EUR, centrado respecto al promedio de su grupo en la copa. Así, se aplica una regresión logística (binomial) que modela la probabilidad de pasar o no pasar la fase de grupos.

El 2018 dicho análisis logró un 88% de efectividad al comparar los clasificados reales con aquellos que tenían más probabilidad de hacerlo en cada grupo según el ajuste del modelo (para ver más detalles de esto pueden ver este hilo de Twitter). Si bien históricamente esta variable económica tiene una influencia de aproximadamente el 70%, implicando que dicha variable influyó particularmente fuerte el año pasado, de todas maneras esto es lo suficientemente alto y nos permite tener una noción acabada de cuáles equipos “deberían” clasificar.

Te invito a jugar con una visualización interactiva realizada en Datawrapper considerando los datos históricos antes mencionados. En el eje X se mapea la variable económica, en el eje Y la probabilidad normalizada por grupo y con color si un equipo clasificó (azul) o no (rojo).

Situando el cursor sobre un punto específico se despliega la información detallada correspondiente, incluyendo nombre del club, año, grupo, valor económico centrado, probabilidad estimada, puntos y resultado obtenido.

Se aprecia que, a partir de aproximadamente los 10 millones de EUR sobre el promedio del grupo o, en otras palabras, tener igual o más de un 35% de probabilidades (normalizada) de clasificar, dicha clasificación se ha concretado en la mayoría de los casos.

Los fracasos más llamativos corresponden a Palmeiras el 2016, Flamengo el 2012 y 2017 e Independiente de Avellaneda el 2011; todos con planteles valorizados en más de 20 millones de EUR sobre el promedio de sus respectivos grupos, pero aún así no clasificaron.

En contraste, las hazañas más notables desde este punto de vista son las clasificaciones de LDU de Quito el 2011, Emelec el 2012, Wilstermann el 2017 y Universitario de Sucre el 2015; todos valorizados en menos de 20 millones de EUR bajo el promedio de sus respectivos grupos.

(Como alternativa, si gustas puedes revisar esta otra versión de la app interactiva, realizada en Shiny, donde además puedes seleccionar un equipo de preferencia en el menú para la facilitar su identificación con color negro. Por defecto marqué el actual campeón: River Plate. La base de datos utilizada y el código de la app lo puedes revisar acá)

  • Estimación 2019

Ahora usaré los datos históricos para estimar las probabilidades de pasar la fase de grupos para los participantes de la edición 2019 según los valores económicos de sus planteles observados en el sitio Transfermarkt con fecha 01 de marzo.

Como verán en la tabla final, existe una gran disparidad entre los equipos desde este punto de vista. Por ejemplo, existe una diferencia de 108.3 millones de EUR entre el máximo (Palmeiras con 112) y el mínimo valor (Wilstermann con 3.7). En general, como ha sido la tónica de los últimos años, destacan los equipos brasileños con los planteles más caros, seguidos luego de los argentinos.

A continuación, el código en R que permite cargar los datos, manipularlos, ajustar el modelo y usarlo para estimar los resultados que se aprecian en la tabla final. Los archivos CSV se pueden descargar desde acá.

library(dplyr)
# Ajusta modelo con datos antiguos (2011-2018)
old_data <- read.csv("data_liberta_2011_18.csv", stringsAsFactors=F,
encoding="utf8")
fit <- glm(factor(clas_factor) ~ Value_centered, old_data,
family='binomial')
# Nuevos datos
new_data <- read.csv("grupos_2019.csv", stringsAsFactors=F,
encoding="utf8")
# Centra valores $ respecto a grupos
mean_values <- new_data %>% group_by(Year, Group) %>%
summarise(mean_value=mean(Value))
new_data <- new_data %>% inner_join(mean_values, by="Group") %>%  
mutate(Value_centered = Value - mean_value)
# Usa modelo para estimar probs. independientes de datos 2019
new <- data.frame(Value_centered = new_data$Value_centered)
p <- predict(fit, newdata = new, type="response")
new_data <- new_data %>% mutate(P_ind=p)
# Normaliza probabilidades por grupo y rankea de mayor a menor
sum_values <- new_data %>% group_by(Group) %>%
summarise(sum_p=sum(P_ind))
new_data <- new_data %>% inner_join(sum_values, by="Group") %>%
mutate(P_norm = round(P_ind/sum_p*100, 1)) %>%
select(Group, Club, Value, Value_centered, P_ind,
P_norm) %>%
arrange(Group, desc(P_norm))
  • Comentarios sobre los resultados

En la mayoría de los grupos hay un claro favorito con cerca del doble de probabilidades de clasificación que su más próximo rival (Cruzeiro, Godoy Cruz, Flamengo, Atlético Mineiro, Palmeiras, Boca Juniors y Gremio), los que deberían quedarse con el primer lugar de sus grupos.

La excepción está en el grupo A, donde los dos favoritos están muy cerca (River Plate e Internacional) y deberían pelearse el primer lugar.

En los demás grupos tenemos distintos escenarios:

1) Una pelea ajustada por el segundo lugar entre dos equipos (B y D);

2) Una pelea ajustada por el segundo lugar entre tres equipos (C y E), pudiendo llamarse “grupos de la muerte”; y

3) El segundo favorito también se escapa respecto a los demás competidores (F, G y H).

Al finalizar la fase de grupos haré el recuento de efectividad de las estimaciones y comentarios de los resultados.

Y luego se viene la parte III. ¡Hasta la próxima!


Actualización post fase de grupos (12–05–2019):

El modelo funciona

Una vez más, así como en las ediciones anteriores, con solo mirar la variable “valor económico del plantel” se puede predecir con alta efectividad cuáles equipos clasifican a 1/8 de final en la Copa Libertadores: esta año con un 81% (13 de 16 equipos).

¿Las sorpresas de la edición 2019?

  • GRUPO B: Huracán estuvo bajo su rendimiento esperado y Emelec ocupó su lugar.
  • GRUPO E: Atlético Mineiro también estuvo bajo las expectativas y Cerro Porteño clasificó en su lugar.
  • GRUPO H: Libertad dio la gran sorpresa positiva, clasificando 1ero cuando sus probabilidades lo dejaban último. Además de que Rosario Central no estuvo a la altura.

Todos los 13 restantes clasificados eran uno de los dos más probables en sus respectivos grupos según el modelo.

A nivel de países (sorpresas) tenemos:

  • 6 Brasil
  • 4 Argentina
  • 3 Paraguay (2)
  • 2 Ecuador (1)
  • 1 Uruguay

Los equipos paraguayos fueron 2 de las 3 sorpresas. En otras ocasiones han sido los bolivianos, que se hacen fuertes de local, y en otras los colombianos o uruguayos, etc. Es variable: La nacionalidad de los equipos no tiene significancia estadística en el modelo. Por eso, si se quiere mejorar aún más éste, hay que buscar otras variables. ¿Rendimiento en el torneo local? ¿El fixture? ¿xG?

Hasta la próxima!