En esta ocasión me voy a centrar en una base de datos que me ha parecido curiosa e interesante. De nuevo la he descargado de Kaggle. Se trata de un dataset con los equipos de fútbol de las principales ligas europeas (temporada 2020-21): premier, liga francesa, liga española, bundesliga y liga italiana.

Se recogen las siguientes variables cuantitativas:

Goals: media de goles por partido.

Shots: media de disparos a puerta por partido.

Yellow_cards: número de tarjetas amarillas en la temporada.

Red_cards: número de tarjetas rojas en la temporada.

Possesion: media del porcentaje del tiempo con posesión del balón en cada partido.

Pass: media de pases acertados por partido.

AerialsWon: media de juegos aéreos ganados por partido.

Rating: puntuación media del equipo.

Así pues vamos a jugar con estos datos para ver diferencias entre las grandes ligas, y si es posible realizar algún tipo de modelo predictivo.

ANÁLISIS EXPLORATORIO Y ESTADÍSTICA DESCRIPTIVA.

El resumen global del dataset lo muestro a continuación. Tenemos 98 equipos, de los que se han recogido 10 variables. La variable Tournament la he transformado a tipo factor para poder manejarla mejor a nivel estadístico.

## 'data.frame':    98 obs. of  10 variables:
##  $ Team        : chr  "Manchester City" "Bayern Munich" "Paris Saint-Germain" "Barcelona" ...
##  $ Tournament  : Factor w/ 5 levels "Bundesliga","LaLiga",..: 4 1 3 2 2 4 5 4 1 2 ...
##  $ Goals       : int  83 99 86 85 67 73 77 55 75 67 ...
##  $ Shots.pg    : num  15.8 17.1 15 15.3 14.4 13.8 15.7 13.7 14.6 12.1 ...
##  $ yellow_cards: int  46 44 73 68 57 64 76 63 43 100 ...
##  $ red_cards   : int  2 3 7 2 2 1 6 4 1 0 ...
##  $ Possession. : num  60.8 58.1 60.1 62.4 57.7 54.5 55.4 49.1 57.5 51.8 ...
##  $ Pass.       : num  89.4 85.5 89.5 89.7 87.7 84.8 88.3 78.6 85.5 83.1 ...
##  $ AerialsWon  : num  12.8 12.9 9.5 10.6 11.8 14.5 11.4 19.4 12.8 14.4 ...
##  $ Rating      : num  7.01 6.95 6.88 6.87 6.86 6.85 6.85 6.84 6.84 6.84 ...

Observamos cómo no tenemos datos perdidos, y tan sólo dos variables de las 10 no son contínuas. Son las correspondientes al nombre de la competición y al nombre del equipo:

En la siguiente tabla muestro el número de equipos en cada una de las 5 competiciones estudiadas:

Competicion Num
Bundesliga 18
LaLiga 20
Ligue 1 20
Premier 20
Serie A 20

Los equipos de cada una de las competiciones son:

Premier_League Bundesliga LaLiga Ligue1 SerieA
Manchester City Bayern Munich Barcelona Paris Saint-Germain Juventus
Manchester United Borussia Dortmund Real Madrid Lille Atalanta
Aston Villa Wolfsburg Atletico Madrid Lyon AC Milan
Chelsea RB Leipzig Sevilla Monaco Napoli
Liverpool Bayer Leverkusen Villarreal Rennes Inter
Tottenham Eintracht Frankfurt Real Sociedad Metz Roma
Leicester Borussia M.Gladbach Real Betis Lens Sassuolo
Leeds VfB Stuttgart Valencia Brest Sampdoria
West Ham Hoffenheim Celta Vigo Marseille Lazio
Everton Union Berlin SD Huesca Montpellier Torino
Arsenal Freiburg Athletic Bilbao Nice Verona
Wolverhampton Wanderers Hertha Berlin Osasuna Nantes Cagliari
Brighton Mainz 05 Eibar Strasbourg Bologna
Burnley Augsburg Deportivo Alaves Reims Udinese
Fulham Arminia Bielefeld Levante Saint-Etienne Genoa
Southampton Werder Bremen Getafe Bordeaux Fiorentina
Newcastle United FC Koln Elche Lorient Spezia
Crystal Palace Schalke 04 Granada Angers Parma Calcio 1913
West Bromwich Albion NA Cadiz Nimes Crotone
Sheffield United NA Real Valladolid Dijon Benevento

ANÁLISIS POR COMPETICIONES.

Podemos empezar comparando cada una de las grandes ligas de forma global. Por ejemplo, ¿Cúal es la competición más goleadora? En el siguiente gráfico boxplot se aprecian las diferencias en goles entre las diferentes ligas:

Se observa que la media de goles más alta la tenemos en la liga Italiana, y la más baja en la Liga española. Los valores exactos los muestro en la siguiente tabla:

Tournament Goals
Bundesliga 51.55556
LaLiga 47.65000
Ligue 1 52.45000
Premier 51.20000
Serie A 58.00000

Los gráficos boxplot para las variables Shots, yellow_Cards, red_cards,Pass y Rating los muestro a continuación. Las variables Possesion y AerialsWon no las incluyo ya que no tienen mucho sentido al comparar competiciones, no así al comparar equipos.

La media de los valores para cada liga son los siguientes:

Shots.pg yellow_cards red_cards Pass. Rating
Bundesliga 12.37222 60.05556 1.833333 79.07222 6.652222
LaLiga 10.66000 81.95000 3.750000 78.44500 6.597500
Ligue1 11.70000 70.95000 5.100000 81.57500 6.638500
Premier 12.09500 54.75000 2.400000 80.61000 6.716500
SerieA 12.48000 79.85000 3.450000 82.37000 6.626500

Llaman la atención algunos de los resultados de la tabla previa, como que la competición con mayor número de tarjetas amarillas es la española, pero la que más tarjetas rojas tiene es la francesa.

A continuación paso a evaluar la normalidad y homocedasticidad multivariante, con vistas a aplicar un MANOVA.

Respecto a la normalidad multivariante, utilizo el test de Mardia. Comprobamos que no se cumple el supuesto de normalidad multivariante:

## $mv.test
##           Test Statistic p-value Result
## 1     Skewness   84.4397  0.0083     NO
## 2     Kurtosis     2.452  0.0142     NO
## 3 MV Normality      <NA>    <NA>     NO
## 
## $uv.shapiro
##              W      p-value UV.Normality
## Goals        0.9694 0.0221  No          
## Shots.pg     0.9711 0.0292  No          
## yellow_cards 0.9829 0.2325  Yes         
## red_cards    0.9429 3e-04   No          
## Pass.        0.978  0.099   Yes         
## Rating       0.9653 0.0109  No

Respecto a la homocedasticidad multivariante, utilizo el test M de Box. Aunque este test es muy sensible a la normalidad, el resultado nos indica que se cumple el criterio de homocedasticidad multivariante:

## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  X
## Chi-Sq (approx.) = 89.101, df = 84, p-value = 0.331

Así pues, en lugar de aplicar el test de MANOVA clásico, utilizaré el MANOVA de PERMUTACIONES que permite aplicarlo en aquellos casos en los que no se cumplen los supuestos previos. Comprobamos que el p-value es muy significativo, así pues rechazamos la igualdad multivariante de medias.

## [1] "p_value: 0"

En la siguiente tabla muestro el análisis univariante (Kruskall-Wallis) de cada variable, junto con su nivel de significación. Comprobamos que las diferencias entre las diferentes ligas se dan en las tarjetas rojas y amarillas:

Variables p_value
Goals 0.4432852
Shots.pg 0.0682376
yellow_cards 0.0000000
red_cards 0.0000407
Pass. 0.0957366
Rating 0.0548472

Para determinar entre qué competiciones son significativas dichas diferencias, aplico el test no paramétrico de Wilcoxon para comparaciones múltiples.

En la siguiente tabla muestro el resultado para el número de tarjetas amarillas, con los p-value para cada par de comparaciones:

Bundesliga LaLiga Ligue 1 Premier
LaLiga 0.0000564 NA NA NA
Ligue 1 0.0078089 0.0550849 NA NA
Premier 0.1214266 0.0000055 0.0001070 NA
Serie A 0.0000523 0.7762781 0.0550849 5.7e-06

A continuación muestro la misma tabla, pero para las tarjetas rojas:

Bundesliga LaLiga Ligue 1 Premier
LaLiga 0.0583559 NA NA NA
Ligue 1 0.0002567 0.3067492 NA NA
Premier 0.6058832 0.3067492 0.0034141 NA
Serie A 0.0136744 0.8800032 0.1863370 0.186337

El siguiente paso, sabiendo que el MANOVA es significativo, sería realizar un análisis discriminante que permita diferencias el perfil de cada liga en base a las variables. Mediante esta técnica puedo representar a las 5 competiciones en un eje de coordenadas en la que la posición relativa de cada liga es proporcional a su similaridad/diferencia respecto a las otras.

El siguiente gráfico representa los eigen-value, con la proporción de variabilidad explicada por cada una de las coordenadas. Observamos que las dos primeras coordenadas explican más del 90% de la variabilidad.

La representación de las 5 competiciones sobre las dos primeras coordenadas canónicas la muestro a continuación:

## Vector scale factor set to 5.27

El biplot previo nos indica que la primera coordenada explica un 71.5% de la variabilidad de las 5 ligas, y la segunda coordenada explica un 18.6%. La primera coordenada hace referencia fundamentalmente a las tarjetas amarillas y al Rating de los clubs en menor medida. La segunda coordenada está relacionada con las tarjetas rojas y con los disparos a puerta en menor grado. De este gráfico se puede concluir que, en base a las variables analizadas (tarjetas amarillas y rojas, disparos a puerta, goles y pases), la liga española (LaLiga) es muy similar a la liga francesa (Ligue1) y en menor medida a la liga italiana (Serie A). A su vez, estas tres ligas presentan mayor diferencia respecto a la Premier y a la Bundesliga.

Un resultado parecido ofrece un Análisis de Proximidad mediante un escalado multidimensional clásico sobre la matriz de distancias de Mahalanobis entre las diferentes ligas. El mapa de las 5 competiciones sobre las dos primeras coordenadas lo muestro a continuación:

## Warning in cmdscale(maha, k = 4, eig = T): only 3 of the first 4 eigenvalues are
## > 0

ANÁLISIS POR EQUIPOS.

Ahora me centraré en el análisis de los diferentes equipos que conforman las 5 ligas europeas. Una pregunta que me parece interesante es la similitud/diferencias entre los distintos equipos, a pesar de militar en ligas diferentes. Para ello realizo un Análisis de Proximidad mediante un escalado multidimensional utilizando en este caso las distancias euclídeas entre los equipos. Esta vez sí que incluyo en el análisis todas las variables recogidas en el modelo.

En el siguiente gráfico muestro el porcentaje de variabilidad explicado por las coordenadas del escalado multidimensional. Vemos que las dos primeras coordenadas explican más del 90% de la variabilidad en las distancias entre los equipos.

Así pues, a continución represento a los equipos de todas las ligas en un mapa dado por estas dos coordenadas:

Si observamos detenidamente, sí que se aprecia un patrón de superposición entre las ligas española, italiana y también francesa, así como entre las ligas inglesa y alemana. Si nos fijamos en equipos particulares, destaca que equipos como el FC Barcelona, Atalanta, Nápoles, Juventus o PSG presentan importantes similitudes, así como el R. Madrid con equipos como el Borussia o el Tottenham. Evidentemente éstas diferencias están limitadas unicamente a las variables estudiadas.

MODELO DE REGRESIÓN:

Por último voy a desarrollar un modelo que permita predecir el Rating de un equipo a partir del resto de variables de juego. Puesto que el tamaño muestral está limitado a 98 equipos, en esta ocasión utilizaré una validación cruzada para calcular el error y validar el modelo.

El gráfico siguiente muestra el error de validación (MSE) de todos los modelos posibles. Vemos que el menor error lo obtenemos con el modelo de 7 variables predictoras.

Los coeficientes de regresión para el modelo de 7 variables regresoras los muestro a continuación:

##  (Intercept)        Goals     Shots.pg yellow_cards    red_cards  Possession. 
##  5.553090929  0.004646647  0.009242305 -0.001646093 -0.002931347  0.003299886 
##        Pass.   AerialsWon 
##  0.006424889  0.011478823

El coeficiente de determinación (R2) lo calculamos:

## Warning in kable_pipe(x = structure("0.8618248", .Dim = c(1L, 1L), .Dimnames =
## list(: The table should have a header (column names)
0.8618248

Ahora paso a realizar el diagnóstico del modelo. En primer lugar compruebo la normalidad de los residuales. Vemos que los valores no siguen una distribución normal.

## 
##  Shapiro-Wilk normality test
## 
## data:  resid
## W = 0.96448, p-value = 0.009466

Con relación a la homocedasticidad de los residuales comprobamos que sí se cumple este criterio.

## 
##  studentized Breusch-Pagan test
## 
## data:  model
## BP = 10.026, df = 7, p-value = 0.1871

Así pues es necesario realizar algún tipo de modificación al modelo, ya que hemos comprobado que no cumple el criterio de normalidad. Las opciones que tenemos son:

1) Transformación de variables: en este caso realizo una transformación de Tukey. Consigo de esta forma normalizar la distribución de los residuales (shapiro test con p-value=0.56), pero a expensas de obtener un modelo más complejo y difícil de interpretar por el tipo de transformación que hay que aplicar a la variable respuesta (se trata de una transformación \(y=y^{-10}\) )

2) Regresión robusta: este tipo de regresión no funciona con este modelo, ya sea mediante una M-Estimación o mediante una regresión LTS.

3) Regresión bootstrap: esta técnica permite calcular los coeficientes de regresión, así como sus intervalos de confianza, cuando no se cumple el criterio de normalidad de los residuales. Los coeficientes, para una simulación de n=3000, los muestro a continuación:

##  (Intercept)        Goals     Shots.pg yellow_cards    red_cards  Possession. 
##  5.557467819  0.004645047  0.009329183 -0.001648927 -0.002929140  0.003275229 
##        Pass.   AerialsWon 
##  0.006378244  0.011456437

Y los intervalos de confianza al 95% son:

Intercept Goals Shots Yellow_cards Red_cards Posesion Pass AerialsWon
2.5% 5.167003 0.0034863 -0.0004279 -0.0023965 -0.0080731 -0.0012910 0.0007431 0.0061235
97.5% 5.960574 0.0057898 0.0197279 -0.0008936 0.0020444 0.0076788 0.0117972 0.0168338

Así pues, podemos concluir que nuestro modelo de regresión de 7 variables permite explicar un 86% de la variabilidad de la variable Rating.

ANÁLISIS DE CONGLOMERADOS:

Por último, y por sacar algo más de punta a estos datos, vamos a imaginar que nos gustaría diseñar tres competiciones pero, para dar más emoción al juego, cada una de las competiciones ha de estar formada por equipos similares. De esta forma, en teoría, serán ligas más disputadas. En este escenario podemos usar un análisis de clústers, de manera que de forma no supervisada obtengamos las ‘familias’ de equipos más parecidas entre sí. Para ello calculo un clúster jerárquico aglomerativo (matriz de distancias euclídea, y método completo), definiendo el número de grupos como k=3:

Así obtenemos tres grandes grupos o competiciones, con 37, 46 y 15 equipos en cada una de ellas. Los equipos que formarían parte de la Competición A serían:

##  [1] "Manchester City"     "Bayern Munich"       "Paris Saint-Germain"
##  [4] "Barcelona"           "Real Madrid"         "Manchester United"  
##  [7] "Juventus"            "Borussia Dortmund"   "Atletico Madrid"    
## [10] "Atalanta"            "Chelsea"             "Liverpool"          
## [13] "AC Milan"            "Lille"               "Tottenham"          
## [16] "Napoli"              "Leicester"           "Inter"              
## [19] "Lyon"                "RB Leipzig"          "Leeds"              
## [22] "Bayer Leverkusen"    "Eintracht Frankfurt" "Monaco"             
## [25] "Roma"                "Sevilla"             "Borussia M.Gladbach"
## [28] "Arsenal"             "Rennes"              "VfB Stuttgart"      
## [31] "Sassuolo"            "Villarreal"          "Real Sociedad"      
## [34] "Brighton"            "Montpellier"         "Nice"               
## [37] "Lazio"

Los equipos que formarían parte de la Competición B serían:

##  [1] "Aston Villa"             "Wolfsburg"              
##  [3] "West Ham"                "Everton"                
##  [5] "Wolverhampton Wanderers" "Metz"                   
##  [7] "Real Betis"              "Lens"                   
##  [9] "Brest"                   "Fulham"                 
## [11] "Marseille"               "Sampdoria"              
## [13] "Hoffenheim"              "Southampton"            
## [15] "Newcastle United"        "Nantes"                 
## [17] "Union Berlin"            "Strasbourg"             
## [19] "Crystal Palace"          "Freiburg"               
## [21] "Valencia"                "Celta Vigo"             
## [23] "Reims"                   "Torino"                 
## [25] "Saint-Etienne"           "Bordeaux"               
## [27] "Hertha Berlin"           "Cagliari"               
## [29] "Bologna"                 "Augsburg"               
## [31] "Udinese"                 "SD Huesca"              
## [33] "Athletic Bilbao"         "Lorient"                
## [35] "Genoa"                   "Angers"                 
## [37] "Werder Bremen"           "Fiorentina"             
## [39] "Nimes"                   "FC Koln"                
## [41] "Levante"                 "Spezia"                 
## [43] "Elche"                   "Crotone"                
## [45] "Benevento"               "Dijon"

Y finalmente los equipos que constituyen la competición C serían:

##  [1] "Burnley"              "Verona"               "Mainz 05"            
##  [4] "Osasuna"              "Arminia Bielefeld"    "Eibar"               
##  [7] "West Bromwich Albion" "Deportivo Alaves"     "Getafe"              
## [10] "Parma Calcio 1913"    "Granada"              "Cadiz"               
## [13] "Real Valladolid"      "Sheffield United"     "Schalke 04"

Y aquí finalizo el análisis de este dataset. Me ha parecido muy interesante, ya que permite jugar con los datos además de combinar diferentes técnicas estadísticas.