This is the dataset of soccer’s Laliga season 2018/2019 where the teams compete for a title. I got this dataset from “kaggle” where Prabhat had created it whose official source is “fbref” website. This dataset has 556 observations and 11 variables. This dataset consists of goals, assists, name, shots, cards, penalties and more which was interesting to work. It contains a lot of variables where I choosed the following:
For Visualization and exploratory plots
goals_scored…17: quantitative
team: categorical
name: categorical
position: categorical
For Correlation and Regression
shots_on_target: quantitative
assists: quantitative
shots: quantitative
successful_dribbles: quantitative
passes: quantitative
minutes_played: quantitative
games_played: quantitative
Cleaning
First, I started with loading the libraries and data, finding out the data was not properly managed. I used “tolower” and “gsub” functions to lowercase and remove space from the variables. Then, I used “select” function to only include those variable I need for the project and stored in “soccer1” variable. There were multiple variables of goal scored, where the true values was stored in “goals_scored…17”, which I renamed to goals.
Why this dataset?
I chose this dataset because I was interested in finding patterns in something different like sports and what I can find new compared to other data. Also, I understand soccer and the stats, so it would not be difficult for me to understand the data.
Loading Libraries and Dataset
library(tidyverse)
Warning: package 'tidyr' was built under R version 4.6.1
Warning: package 'readr' was built under R version 4.6.1
Warning: package 'dplyr' was built under R version 4.6.1
Warning: package 'forcats' was built under R version 4.6.1
Warning: package 'lubridate' was built under R version 4.6.1
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
New names:
Rows: 556 Columns: 62
── Column specification
──────────────────────────────────────────────────────── Delimiter: "," chr
(7): Team, Position, Name, Percentage of games played, Percentage of fu... dbl
(55): Shirt number, Minutes played, Games played, Full games played, Gam...
ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
Specify the column types or set `show_col_types = FALSE` to quiet this message.
• `Goals scored` -> `Goals scored...17`
• `Penalties scored` -> `Penalties scored...18`
• `Tackles` -> `Tackles...21`
• `Goals scored` -> `Goals scored...44`
• `Penalties scored` -> `Penalties scored...49`
• `Tackles` -> `Tackles...54`
Cleaning of the Data-set
# Variables lower-cased and removed space, included "_"names(soccer) <-tolower(names(soccer))names(soccer) <-gsub(" ","_", names(soccer))# selecting the variables required for the project and storing in new data-setsoccer1 <- soccer |>rename(goals = goals_scored...17) |>select(team, goals, name, position, shots_on_target, assists, shots, successful_dribbles, passes, minutes_played, games_played)
Exploratory Plots
# Bar chart of players by their positionggplot(soccer1, aes(x = position, fill = position)) +geom_bar() +scale_fill_brewer(palette ="Set2") +theme_minimal() +labs(title ="Players by Position",x ="Position",y ="Number of players", fill ="Position",caption ="Source: FBref, 2018-2019 La Liga Stats")
# Box-plot of goals by the positionggplot(soccer1, aes(x = position, y = goals, fill = position)) +geom_boxplot() +theme_minimal() +labs(title ="Goals Scored by Position",x ="Position",y ="Goals", fill ="Position",caption ="Source: FBref, 2018-2019 La Liga Stats")
Visualizations
In the first visualization, I tried to find which club in La Liga had scored the most goals which resulted in FC Barcelona having 87 goals, followed by Real Madrid and Seville FC. I grouped it by team and used summarize to sum the goals. Then, I used ggplot to make the scatter-plot where I included my understandings and changed the color, I also flipped the plot because the club would be mixed together which results in bad visualization.
1
g1 <- soccer1 |># grouping by team group_by(team) |># summing clubs with most goals summarize(top_goals =sum(goals)) |># arranging top to lowarrange(desc(top_goals))# creating scatter plot and flipping the variableslibrary(RColorBrewer)
Warning: package 'RColorBrewer' was built under R version 4.6.1
ggplot(g1, aes(x =reorder(team, top_goals), y = top_goals, color = top_goals)) +geom_point(size =2) +# using different colorscale_color_distiller(palette ="Set1") +coord_flip() +theme_minimal() +annotate("text", x =4, y =70, label ="FC Barcelona scored\nthe most: 87 goals") +# adding labelslabs(title ="Total Goals Scored by Each La Liga Team",x ="Team",y ="Total Goals",color ="Total goals",caption ="Source: FBref, 2018-2019 La Liga Stats")
In the second visualization, I tried to find the players with most goals which also mentions clubs they played for. The result shows that Lionel Messi is the top goal scorer of the season with 36 goals. Also, I only selected Midfielder and Forward as only those two position could have more goals rather than Defender and Goalkeeper. I again played with the code so I can present in a proper way. In this visualization, I used “plotly” to make the plot interactive.
2
top_scorers <- soccer1 |># Filtering only Midfielder and Forward playersfilter(position %in%c("Midfielder", "Forward")) |>group_by(team) |># keeping one player from one club who has highest goalslice_max(goals, n =1, with_ties =FALSE) |>ungroup()top <-ggplot(top_scorers, aes(x =reorder(name, goals), y = goals, fill = goals)) +geom_col(size =3) +# arranging the labelsgeom_text(aes(label = team), hjust =-0.2, size =2, color ="black") +# keeping the y-axis limit to 40expand_limits(y =40) +# flipping the graph as it is mixed in normal coord_flip() +annotate("text", x =4, y =30, label ="Messi is the top goal scorer\nwith 36 goals") +# using different colorscale_fill_distiller(palette ="Set2") +theme_minimal() +# labelslabs(title ="Top Goal Scorer in La Liga Club, 2018-2019 Season",x ="Player",y ="Goals scored",fill ="Goals",caption ="Source: FBref, 2018-2019 La Liga Stats")
Warning in geom_col(size = 3): Ignoring unknown parameters: `size`
# Using interactive chartslibrary(plotly)
Warning: package 'plotly' was built under R version 4.6.1
Attaching package: 'plotly'
The following object is masked from 'package:ggplot2':
last_plot
The following object is masked from 'package:stats':
filter
The following object is masked from 'package:graphics':
layout
ggplotly(top, tooltip ="y")
Correlation Plot
I tried to find the relation between my selected variables, which is connected with each other.
library(DataExplorer)
Warning: package 'DataExplorer' was built under R version 4.6.1
cors <- soccer1 |># selecting only required data for correlationselect(goals, shots_on_target, assists, successful_dribbles, games_played, passes)plot_correlation(cors)
Multiple Regression
Lastly, I did multiple regression to end my project where I tried wanted to find what influences goals, is it passes, shots, duration or something else also has some contributions.
I started with a full model containing shots on target, assists, successful dribbles, games played, passes, and minutes played. Using backward elimination, I removed the variables with the highest p-values (games played, passes, and minutes played) and re-run the model. Minutes played also had problems in the original file.
All three predictors are significant at the 0.05 level. Shots on target and successful dribbles have p-values below 0.001, and assists has a p-value of 0.049, which is only just under the cutoff. Overall, F-test is also significant (p < 0.001), so the model predicts goals better than chance.
The adjusted R² is about 0.863, so the model explains roughly 86% of the variation in goals, after adjusting for the number of predictors.
I did not spend a lot of time in finding the duration of games played by each player which can affect the result. In future, I would spend some time on finding player’s game time and their progress. The difficulties I came across were that, I had to go through official source to find out the real data of goals scored and ignore other variable. Also, the dataset is named season 2019/2020, when I researched about the season it was actually 2018/2019.