El fútbol inglés, en particular la Premier League, es una de las ligas más populares y competitivas del mundo. En este proyecto se realizará un análisis estadístico descriptivo de los partidos de la Premier League durante la temporada 2022-2023, utilizando el lenguaje de programación R. El objetivo es explorar variables como asistencia al estadio, goles anotados, tarjetas recibidas, entre otras; con el fin de entender mejor el desempeño de los equipos y describir características importantes de esta liga.
¿Existen patrones y relaciones estadísticamente significativas entre las variables de asistencia al estadio, goles anotados, tarjetas recibidas y resultados finales en los partidos de la Premier League 2022-2023?
Para tener una vista preliminar de la estructura y contenido de los datos, se utilizó la función head() para visualizar las primeras 5 filas del dataset Clean_Data1. La función head() es muy útil en el análisis exploratorio de datos, ya que permite inspeccionar rápidamente una muestra representativa de las observaciones contenidas en el conjunto de datos de interés.
head(Clean_Data1, 5)
Para obtener una comprensión inicial de la estructura y contenido de los datos, se generó un resumen estadístico del dataset Clean_Data1 utilizando la función skim() del paquete skimr en R. Clean_Data1 contiene 380 observaciones y 26 variables, donde 20 son numéricas y 6 de tipo caracter.
Las variables de tipo caracter corresponden a month, stadium, location, attendance_category, Home Team y Away Team. Para las variables numéricas se presentan estadísticos como recuento de valores no vacíos, media, desviación estándar, valores mínimos y máximos, y cuartiles. Esto permite explorar la distribución, dispersión y resumen de los datos de forma rápida antes de un análisis más profundo. Algunos puntos importantes del resumen son:
skim(Clean_Data1)
| Name | Clean_Data1 |
| Number of rows | 380 |
| Number of columns | 27 |
| _______________________ | |
| Column type frequency: | |
| character | 6 |
| numeric | 21 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| month | 0 | 1 | 3 | 9 | 0 | 10 | 0 |
| stadium | 0 | 1 | 7 | 25 | 0 | 20 | 0 |
| location | 0 | 1 | 4 | 6 | 0 | 4 | 0 |
| attendance_category | 0 | 1 | 4 | 5 | 0 | 3 | 0 |
| Home Team | 0 | 1 | 6 | 24 | 0 | 20 | 0 |
| Away Team | 0 | 1 | 6 | 24 | 0 | 20 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| month_n | 0 | 1 | 5.81 | 3.09 | 1 | 3.00 | 6 | 9.00 | 10 | ▅▆▃▅▇ |
| attendance | 0 | 1 | 40231.76 | 16356.43 | 9972 | 29418.25 | 37947 | 53290.75 | 75546 | ▂▇▅▆▂ |
| Goals Home | 0 | 1 | 1.63 | 1.42 | 0 | 1.00 | 1 | 2.00 | 9 | ▇▅▁▁▁ |
| Away Goals | 0 | 1 | 1.22 | 1.18 | 0 | 0.00 | 1 | 2.00 | 6 | ▇▂▁▁▁ |
| total_goals | 0 | 1 | 2.85 | 1.79 | 0 | 2.00 | 3 | 4.00 | 9 | ▅▇▅▂▁ |
| home_shots | 0 | 1 | 13.97 | 5.60 | 1 | 10.00 | 14 | 17.00 | 33 | ▂▇▇▂▁ |
| away_shots | 0 | 1 | 11.31 | 4.91 | 1 | 8.00 | 11 | 15.00 | 30 | ▃▇▅▂▁ |
| total_shots | 0 | 1 | 25.29 | 5.89 | 11 | 21.00 | 25 | 29.00 | 45 | ▂▇▇▃▁ |
| home_corners | 0 | 1 | 5.64 | 3.07 | 0 | 3.00 | 5 | 8.00 | 17 | ▆▇▆▁▁ |
| away_corners | 0 | 1 | 4.47 | 2.82 | 0 | 2.00 | 4 | 6.00 | 19 | ▇▇▂▁▁ |
| total_corners | 0 | 1 | 10.11 | 3.26 | 2 | 8.00 | 10 | 12.00 | 21 | ▁▇▇▂▁ |
| home_fouls | 0 | 1 | 10.61 | 3.27 | 3 | 8.00 | 10 | 13.00 | 23 | ▂▇▅▂▁ |
| away_fouls | 0 | 1 | 10.96 | 3.48 | 3 | 8.75 | 11 | 13.00 | 25 | ▃▇▆▁▁ |
| total_fouls | 0 | 1 | 21.57 | 5.22 | 10 | 18.00 | 21 | 25.00 | 41 | ▃▇▆▂▁ |
| home_yellow | 0 | 1 | 1.68 | 1.26 | 0 | 1.00 | 2 | 3.00 | 6 | ▇▅▃▁▁ |
| away_yellow | 0 | 1 | 1.94 | 1.36 | 0 | 1.00 | 2 | 3.00 | 7 | ▇▆▅▁▁ |
| total_yellow | 0 | 1 | 3.62 | 1.95 | 0 | 2.00 | 3 | 5.00 | 9 | ▂▇▆▃▁ |
| home_red | 0 | 1 | 0.05 | 0.25 | 0 | 0.00 | 0 | 0.00 | 2 | ▇▁▁▁▁ |
| away_red | 0 | 1 | 0.03 | 0.16 | 0 | 0.00 | 0 | 0.00 | 1 | ▇▁▁▁▁ |
| total_red | 0 | 1 | 0.08 | 0.30 | 0 | 0.00 | 0 | 0.00 | 2 | ▇▁▁▁▁ |
| total_cards | 0 | 1 | 3.69 | 1.97 | 0 | 2.00 | 3 | 5.00 | 10 | ▆▇▅▂▁ |
# Librerías
# Crear histograma
bins <- hist(Clean_Data1$total_goals, plot = FALSE)$breaks
histogram <- hist(Clean_Data1$total_goals, breaks = bins, plot = FALSE)
# Gráfico con Plotly
plot_ly(
x = histogram$mids,
y = histogram$counts,
type = 'bar',
marker = list(line = list(width = 0)),
xaxis = "total_goals", # Título eje X
yaxis = "Frecuencia" # Título eje Y
)
Clean_Data1 %>%
plot_ly(x = ~total_goals) %>%
add_histogram() %>%
layout(
xaxis = list(title = "Goles"),
yaxis = list(title = "Frecuencia")
)
El histograma de goles totales muestra una distribución moderadamente asimétrica y sesgada hacia la derecha, donde las mayores frecuencias se ubican en los intervalos centrales entre 1 y 3 goles, con la moda situándose en 2.
A medida que aumenta el número de goles, las frecuencias decrecen progresivamente, evidenciando que partidos con 6 o más anotaciones son menos comunes en la liga.
La asimetría positiva indica la existencia de algunos valores atípicos altos (partidos muy goleados), que extienden la cola derecha de la distribución más allá de lo esperado bajo normalidad.La variable total goals presenta una media de 2.85 goles, lo cual indica que el promedio de goles por observación se encuentra alrededor de 3 goles. La mediana tiene un valor de 3 goles, este valor separa la distribución de la variable en dos partes iguales, por lo que podemos decir que el 50% de las observaciones tiene 3 o menos goles.
La desviación estándar de 1.79 goles indica que los datos están dispersos alrededor de la media, con una diferencia promedio de casi 2 goles. El coeficiente de asimetría positivo de 0.69 muestra que la distribución se encuentra sesgada hacia la derecha, es decir, hay más observaciones con valores superiores a la media que inferiores. La curtosis de 3.3 indica que la distribución es leptocúrtica, tiene colas más gruesas y una mayor concentración alrededor de la media en comparación con la distribución normal.
El primer cuartil en 2 goles señala que el 25% de los datos son menores o iguales a 2 goles. El tercer cuartil es 4, por lo que el 75% de los datos son menores o iguales a 4 goles. En conclusión, la variable total goals presenta una concentración de valores alrededor de la media de 2.85 y mediana de 3 goles, con presencia de valores extremos y asimetría positiva.# Cálculos estadísticos
media_goals <- mean(Clean_Data1$total_goals)
mediana_goals <- median(Clean_Data1$total_goals)
desviacion_estandar <- sd(Clean_Data1$total_goals)
asimetria <- moments::skewness(Clean_Data1$total_goals)
curtosis <- moments::kurtosis(Clean_Data1$total_goals)
cuartiles <- quantile(Clean_Data1$total_goals, probs = c(0.25, 0.5, 0.75))
coeficiente_variacion <- (desviacion_estandar / media_goals) * 100
# Crear una tabla de resumen
summary_table <- data.frame(
Estadística = c("Media", "Mediana", "Desviación Estándar", "Coef. Asimetria", "Curtosis", "Primer Cuartil", "Mediana", "Tercer Cuartil"),
Valor = c(media_goals, mediana_goals, desviacion_estandar, asimetria, curtosis, cuartiles[1], cuartiles[2], cuartiles[3])
)
knitr::kable(summary_table, format = "html")
| Estadística | Valor |
|---|---|
| Media | 2.8526316 |
| Mediana | 3.0000000 |
| Desviación Estándar | 1.7910267 |
| Coef. Asimetria | 0.6937947 |
| Curtosis | 3.3008021 |
| Primer Cuartil | 2.0000000 |
| Mediana | 3.0000000 |
| Tercer Cuartil | 4.0000000 |
library(plotly)
# Datos
g1 <- Clean_Data1$total_goals
g2 <- Clean_Data1$`Goals Home`
g3 <- Clean_Data1$`Away Goals`
# Gráfico
fig <- plot_ly(type='box')
fig <- fig %>% add_boxplot(y = g1, name = "Goles", marker = list(color = 'rgb(7,40,89)'),
line = list(color = 'rgb(7,40,89)'))
fig <- fig %>% add_boxplot(y = g2, name = "Goles-Local", marker = list(color = 'rgb(9,56,125)'),
line = list(color = 'rgb(9,56,125)'))
fig <- fig %>% add_boxplot(y = g3, name = "Goles-Visitante", marker = list(color = 'rgb(8,81,156)'),
line = list(color = 'rgb(8,81,156)'))
fig <- fig %>%
layout(title = "Boxplot para goles",
xaxis = list(title = "Categoría"),
yaxis = list(title = "Goles"))
# Mostrar
fig
El análisis comparativo de los boxplots para las variables Goles, Goles-Local y Goles-Visitante revela diferencias importantes en las distribuciones de estas métricas.
En términos de tendencia central, la mediana de Goles-Local (1 gol) supera ligeramente a la de Goles-Visitante (1 gol), lo que indica una leve superioridad del equipo anfitrión en la cantidad de anotaciones. Sin embargo, la mediana general de Goles es de 3 goles, evidenciando que en promedio los partidos suelen ser más parejos entre locales y visitantes.
Respecto a la dispersión, el rango intercuartílico de Goles-Local (Q1=1; Q3=2) es también mayor al de Goles-Visitante (Q1=0; Q3=2), denotando una distribución más amplia y variable en los goles anotados cuando el equipo juega como local. Esto podría deberse a un mejor desempeño ofensivo inducido por el aliento de la fanaticada local.
En cuanto a los valores extremos, llama la atención la existencia de 41 valores atípicos en Goles-Local con un máximo de 9 goles, frente a solo 1 valor atípico y 6 goles máximos en Goles-Visitante. Esta asimetría indica que, si bien en la mayoría de partidos los goles suelen ser similares, cuando existen goleadas éstas tienden a darse a favor del equipo que juega en casa.
En conclusión, el análisis estadístico descriptivo evidencia una moderada superioridad del equipo local, impulsada por una mayor dispersión y frecuencia de valores extremos en los goles anotados cuando juega ante su fanaticada. Estos hallazgos son relevantes para entender el comportamiento del equipo como anfitrión versus su desempeño como visitante.library(plotly)
# Datos
y1 <- Clean_Data1$total_goals[Clean_Data1$attendance_category=="Baja"]
y2 <- Clean_Data1$total_goals[Clean_Data1$attendance_category=="Media"]
y3 <- Clean_Data1$total_goals[Clean_Data1$attendance_category=="Alta"]
# Gráfico
fig <- plot_ly(type='box')
fig <- fig %>% add_boxplot(y = y1, name = "Baja", marker = list(color = 'rgb(7,40,89)'),
line = list(color = 'rgb(7,40,89)'))
fig <- fig %>% add_boxplot(y = y2, name = "Media", marker = list(color = 'rgb(9,56,125)'),
line = list(color = 'rgb(9,56,125)'))
fig <- fig %>% add_boxplot(y = y3, name = "Alta", marker = list(color = 'rgb(8,81,156)'),
line = list(color = 'rgb(8,81,156)'))
fig <- fig %>%
layout(title = "Goles anotados por categoría de asistencia al estadio",
xaxis = list(title = "Categoría"),
yaxis = list(title = "Goles"))
# Mostrar
fig
En términos de tendencia central, se observa un incremento en la mediana de Goles conforme aumenta la asistencia al estadio, pasando de 2 goles en Baja, a 2 goles en Media y 3 goles en Alta. Esto indica que a mayor cantidad de aficionados presenciando el partido, tiende a haber una mayor cantidad de goles anotados.
Analizando la dispersión, los rangos intercuartílicos son similares en las 3 categorías, yendo de 2-3.75 en Baja, 1-4 en Media y 2-4 en Alta. Esto significa que independientemente de la asistencia, existe una variabilidad parecida en la distribución de los goles.
En cuanto a los valores atípicos, Baja y Media tienen 1 cada una, mientras que en Alta no se detectan. El valor máximo es similar entre los grupos, de 7 a 9 goles. Por tanto, la asistencia al estadio no tiene un efecto importante en la existencia de valores extremos de goles, aunque tienden a ser levemente más frecuentes cuando hay menos público.
En síntesis, a mayor asistencia de aficionados al estadio, se da un pequeño incremento en la tendencia central de goles anotados. Sin embargo, la dispersión y valores atípicos son similares entre las categorías. Estos hallazgos sugieren un moderado efecto positivo de una mayor fanaticada presencial en el desempeño goleador del equipo local.# Calcular promedio de goles por mes
goals_by_month <- Clean_Data1 %>%
group_by(month_n) %>%
summarise(avg_goals = mean(total_goals))
# Crear gráfico con plotly
fig <- plot_ly(goals_by_month, x = ~month_n, y = ~avg_goals, type = "scatter", mode = "lines")
# Agregar título y ejes
fig <- fig %>%
layout(title = "Promedio de goles por mes",
xaxis = list(title = "Mes"),
yaxis = list(title = "Promedio de goles"))
# Mostrar gráfico
fig
# Calcular promedio de goles por mes
goals_by_month <- Clean_Data1 %>%
group_by(month_n) %>%
summarise(avg_goals = mean(total_goals))
# Crear tabla con kable
knitr::kable(goals_by_month, caption = "Promedio de goles por mes")
| month_n | avg_goals |
|---|---|
| 1 | 2.897959 |
| 2 | 3.111111 |
| 3 | 2.627119 |
| 4 | 3.300000 |
| 5 | 2.944444 |
| 6 | 2.257143 |
| 7 | 2.325000 |
| 8 | 2.967742 |
| 9 | 3.306452 |
| 10 | 2.979167 |
El inicio de la temporada en el mes de Agosto muestra un promedio bajo de goles (2.89), lo cual puede atribuirse a que los equipos se encuentran en la etapa de pretemporada con condiciones físicas no óptimas y aún en proceso de ajuste de esquemas tácticos y alineaciones.
En los meses de Septiembre y Octubre se observa un aumento paulatino del promedio de goles, alcanzando 3.11 y 3.26 goles respectivamente. Esto responde a una mejora en la forma física y táctica de los equipos a medida que avanza la temporada y se establecen los esquemas de juego.
El mes de Noviembre presenta un pico en el promedio de goles (3.30), justo previo al parón navideño. Esto puede deberse a la urgencia de los equipos por sumar puntos antes del periodo de descanso invernal, lo que incrementa el ritmo de competencia.
Luego del parón en Diciembre, se aprecia una baja drástica en el promedio de goles (2.94), resultado esperable considerando que los jugadores pierden ritmo y condición física durante este periodo de inactividad.
Tras el regreso de vacaciones en Enero, el promedio se mantiene bajo (2.25) debido a que los equipos requieren un periodo de readaptación tanto física como táctica antes de retomar su mejor forma.
En los meses de Febrero y Marzo se observa un repunte paulatino del promedio de goles, alcanzando 2.32 y 2.96 respectivamente, a medida que los equipos recuperan el ritmo de competencia y su mejor forma deportiva.
El mes de Abril presenta un pico máximo en el promedio de goles (3.30), cuando los equipos alcanzan su mejor estado físico y táctico durante la temporada. En esta etapa se suelen definir posiciones importantes en la tabla de clasificación.
Finalmente, en Mayo se aprecia un leve descenso del promedio de goles (2.97) hacia el final de la temporada, cuando algunos equipos ya no compiten por objetivos lo que reduce la urgencia y ritmo de juego.# Calcular promedio de asistencia por estadio
df_estadios <- Clean_Data1 %>%
group_by(stadium) %>%
summarise(asistencia_prom = mean(attendance))
df_estadios %>% arrange(desc(asistencia_prom))
fig <- plot_ly(df_estadios, x = ~stadium, y = ~asistencia_prom, type = 'bar')
fig <- fig %>%
layout(title = 'Asistencia promedio por estadio',
xaxis = list(title = 'Estadio', tickangle = 90),
yaxis = list(title = 'Asistencia promedio'))
fig
Al analizar la asistencia promedio a los estadios, se puede evidenciar que el estadio del Manchester United (Old Trafford) presenta el mejor promedio de asistencia entre los estadios de la Premier League. Esto puede explicarse por varios factores:
El Manchester United es uno de los equipos más populares a nivel mundial, con aficionados no solo en Inglaterra sino globalmente. Su enorme base de seguidores se traduce en una alta demanda por entradas para sus partidos locales.
Old Trafford tiene una capacidad de 74,000 espectadores, siendo uno de los estadios de mayor aforo. Esto permite albergar una gran cantidad de aficionados en cada juego.
El estadio cuenta con instalaciones de primer nivel y excelente infraestructura para los espectadores, lo que ofrece una experiencia cómoda y agradable.
El Manchester United suele tener un desempeño destacado en la liga, clasificando consistentemente a competencias europeas. Ello genera interés por presenciar los juegos.
Existe una fuerte tradición e identidad de aficionados que se mantienen leales al equipo independiente de sus resultados. Los partidos del Manchester United se consideran un evento social y de entretenimiento que atrae no solo a los hinchas sino al público general.
# Gráfico 1: Total goles vs Total corners
p1 <- plot_ly(data = Clean_Data1, x = ~total_corners, y = ~total_goals,
type = "scatter", mode = "markers")
# Gráfico 2: Total goles vs Total shots
p2 <- plot_ly(data = Clean_Data1, x = ~total_shots, y = ~total_goals,
type = "scatter", mode = "markers")
# Gráfico 2: Total faltas vs Total tarjetas
p3 <- plot_ly(data = Clean_Data1, x = ~total_fouls, y = ~total_cards,
type = "scatter", mode = "markers")
# Mostrar gráficos
p1
p2
p3
# Coeficiente para Goles vs Corners
cor(Clean_Data1$total_goals, Clean_Data1$total_corners)
## [1] -0.0289071
# Coeficiente para Goles vs Tiros
cor(Clean_Data1$total_goals, Clean_Data1$total_shots)
## [1] 0.2560634
# Coeficiente para Goles vs Tiros
cor(Clean_Data1$total_fouls, Clean_Data1$total_cards)
## [1] 0.4537962
La correlación entre goles totales y corners totales es débil y negativa, con un valor de -0.0289071. Esto sugiere que no existe una asociación fuerte entre una mayor cantidad de córners cobrado en un partido y la cantidad de goles anotados. Los datos indican que ambas variables se comportan prácticamente de manera independiente.
En cuanto a la correlación entre goles totales y tiros totales, se observa un coeficiente de 0.2560634. Aunque la magnitud es baja, al ser positivo señala que existe cierta asociación directa entre una mayor cantidad de remates en un partido y una mayor cifra de anotaciones. Sin embargo, al estar por debajo de 0.3 se considera una correlación débil entre estas variables ofensivas.
Finalmente, la correlación entre faltas totales y tarjetas totales presenta un valor moderado de 0.4537962. Siendo mayor a 0.4, evidencia que ambas variables tienen una asociación directa de magnitud media. Es decir, partidos con mayor cantidad de faltas tienden a tener también una mayor cantidad de tarjetas mostradas por el árbitro, comportamiento esperable dentro de un partido de fútbol.
La variable de goles totales por partido presenta una distribución asimétrica positiva, con mediana de 3 goles y media de 2.85, indicando la existencia de valores extremos superiores que sesgan la media.
Se evidencia un mejor desempeño goleador de los equipos cuando juegan como locales, impulsado por una mayor dispersión y frecuencia de valores atípicos en los goles anotados ante su afición.
Existe un efecto positivo moderado de una mayor asistencia de aficionados sobre la tendencia central de goles anotados por el equipo local. Sin embargo, valores atípicos y dispersión son similares entre categorías de asistencia.
El promedio de goles por mes fluctúa en función del calendario, con repuntes previo a periodos de inactividad y caídas posteriores durante la readaptación física y táctica.
No se hallaron correlaciones fuertes entre variables ofensivas como tiros al arco, córners y goles anotados. La evidencia no respalda contundentemente las suposiciones intuitivas sobre estas relaciones.
Existe una correlación media entre faltas totales y tarjetas totales, indicando que partidos con mayor cantidad de infracciones tienden también a tener mayor cantidad de tarjetas mostradas.