Washington Spirit Heatmap by Gerardo Sandoval

Kiyoshi Mio-USA TODAY Sports

Introduction

The dataset I used covers data for the NWSL 2023 season, focusing on player performance statistics for all teams in the league, including goals, assists, chances created, fouls committed, and more. As a DC sports fan, I decided to focus only on the 24 woman roster of the professional soccer team Washington Spirit.

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.0     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.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
setwd("/Users/gerardosandoval/Downloads")
nwsl <- read_csv("nwsl.csv")
New names:
Rows: 347 Columns: 42
── Column specification
──────────────────────────────────────────────────────── Delimiter: "," chr
(4): team, player_name, conc_player_name, position dbl (38): games_played,
games_started, minutes_played, goals, accurate_pass_...
ℹ 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.
• `accurate_pass_percentage` -> `accurate_pass_percentage...9`
• `accurate_pass_percentage` -> `accurate_pass_percentage...31`

Cleaning Data

names(nwsl) <- tolower(names(nwsl))
names(nwsl) <- gsub(" ", "_", names(nwsl))
nwsl
# A tibble: 347 × 42
   team         player_name conc_player_name position games_played games_started
   <chr>        <chr>       <chr>            <chr>           <dbl>         <dbl>
 1 Orlando Pri… Kerry Abel… KERRYABELLO      DEFENDER           20            14
 2 Chicago Red… Jillienne … JILLIENNE COLEA… MIDFIEL…           11             1
 3 San Diego W… Amirah Ali  AMIRAHALI        FORWARD            17             5
 4 Orlando Pri… Amanda All… AMANDAALLEN      FORWARD             3            NA
 5 Houston Dash Michelle A… MICHELLEALOZIE   FORWARD            17            13
 6 Houston Dash Emily Alva… EMILYALVARADO    GOALKEE…            0            NA
 7 Bay FC       Joelle And… JOELLEANDERSON   MIDFIEL…           18            13
 8 Angel City … Angelina A… ANGELINAANDERSON GOALKEE…            5             5
 9 Houston Dash Andressa    ANDRESSA         MIDFIEL…            5             4
10 Orlando Pri… Angelina    ANGELINA         MIDFIEL…            4            NA
# ℹ 337 more rows
# ℹ 36 more variables: minutes_played <dbl>, goals <dbl>,
#   accurate_pass_percentage...9 <dbl>, assists <dbl>,
#   assists_avg_over_90_mins <dbl>, total_scoring_attempts <dbl>,
#   on_target_scoring_attempts <dbl>, total_attacking_assists <dbl>,
#   tackles <dbl>, fouls_committed <dbl>, fouls_suffered <dbl>,
#   total_offside <dbl>, yellow_cards <dbl>, red_cards <dbl>, …

Filtering to Washington Spirit Players Only

nwsl2 <- nwsl %>%
  filter(team == "Washington Spirit")
nwsl2
# A tibble: 24 × 42
   team         player_name conc_player_name position games_played games_started
   <chr>        <chr>       <chr>            <chr>           <dbl>         <dbl>
 1 Washington … Nicole Ren… NICOLE RENEEBAR… GOALKEE…            3             2
 2 Washington … Lyza Bosse… LYZABOSSELMANN   GOALKEE…            0            NA
 3 Washington … Amber Jean… AMBER JEANBROOKS DEFENDER           13             6
 4 Washington … Annaïg But… ANNAÏGBUTEL      DEFENDER            7             5
 5 Washington … Gabrielle … GABRIELLECARLE   DEFENDER           22            22
 6 Washington … Nicole Dou… NICOLEDOUGLAS    FORWARD            10             1
 7 Washington … Madison El… MADISONELWELL    MIDFIEL…            4             1
 8 Washington … Ashley Hat… ASHLEYHATCH      FORWARD            22            22
 9 Washington … Victoria L… VICTORIA LAUREN… MIDFIEL…            1            NA
10 Washington … Inès Jaure… INÈSJAURENA      MIDFIEL…           13            12
# ℹ 14 more rows
# ℹ 36 more variables: minutes_played <dbl>, goals <dbl>,
#   accurate_pass_percentage...9 <dbl>, assists <dbl>,
#   assists_avg_over_90_mins <dbl>, total_scoring_attempts <dbl>,
#   on_target_scoring_attempts <dbl>, total_attacking_assists <dbl>,
#   tackles <dbl>, fouls_committed <dbl>, fouls_suffered <dbl>,
#   total_offside <dbl>, yellow_cards <dbl>, red_cards <dbl>, …

Heatmap

nwsl <- nwsl2[order(nwsl2$goals),]
row.names(nwsl2) <- nwsl2$player_name
Warning: Setting row names on a tibble is deprecated.
nwsl <- nwsl[,5:10]
nwsl2_matrix <- data.matrix(nwsl2)
nwsl2_heatmap <- heatmap(nwsl2_matrix, 
                       Rowv=NA,  
                       Colv=NA, 
                       col = topo.colors(25), 
                       scale="column", 
                       margins=c(5,10),
                       xlab = "Player Stats",
                       ylab = "Player Name",
                       main = "Washington Spirit Player Stats for 2023 season")

Final Thoughts

In my data cleaning process, the dataset did not contain any NA values. Instead, the source used 0’s to represent anything not aplicable. My cleaning focused entirely on the columns. I used the tolower() and gsub() functions to ensure all column names were in lowercase letters and spaces were replaced with underscores.The visual represents player statistics across 21 columns. It was no surprise that Trinity Rodman had impressive offensive statistics, given her high participation in the attacking third. However, I was surprised to see that Paige Metayer had a high dribbling rate and many completed passes but did not record any assists over the season.As I am relatively new to creating heatmaps, there were several elements I wanted to include but struggled with. Firstly, I was unable to select specific columns for the x-axis eventhough I was using the [#,#] function. Additionally, I wanted to make the x and y-axis text smaller and angled for better readability but struggled to do so. I also wanted to add a legend to my heatmap. However, I found that features like angling text and adding legends work differently unless using the ggplot package. I definitely want to make edits to my heatmap in the near future when I expand my knowledge.