brady <- read.csv("Brady.csv")
mahomes <- read.csv("Mahomes.csv")
manning <- read.csv("Manning.csv")
montana <- read.csv("Montana.csv")
montana$QBR <- NA
nfl_data <- rbind(brady, mahomes, manning, montana)
brady$Player <- "Brady"
mahomes$Player <- "Mahomes"
manning$Player <- "Manning"
montana$Player <- "Montana"
nfl_data <- rbind(brady, mahomes, manning, montana)
nfl_data <- nfl_data[!grepl("Career|yrs", nfl_data$Year, ignore.case = TRUE),]
nfl_data$Year <- as.numeric(gsub("[^0-9]", "", nfl_data$Year))
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
nfl_data <- nfl_data %>% group_by(Player) %>% mutate(Season = rank(Year))
In my initial plot I have created a scatter plot with passer ratings over seasons color-coded by quarterback. My goal with this visualization will be to display how Mahomes is the best quarterback in his short career. Although the data is displayed, it is unfortunately too visually taxing, and the y axis appears to have too many tick marks. It is also difficult to see how passer rating changes by quarterback over time.
library(ggplot2)
ggplot(nfl_data, aes(x=Season, y=Rate, group=Player, color=Player)) +
geom_point() +
theme_minimal() +
labs(x = "Year in NFL", y = "Passer Rating", title = "Quarterback Comparison") +
theme(legend.title = element_blank())
Now I have altered the aesthetic property by changing the type of graph to a stacked line graph. While the ratings are now connected by their respective quarterbacks, the amount of data is still visually overwhelming.
library(ggplot2)
ggplot(nfl_data, aes(x=Season, y=Rate, group=Player, color=Player)) +
geom_line(linetype="dotted") +
geom_point() +
theme_minimal() +
labs(x = "Year in NFL", y = "Passer Rating", title = "Quarterback Comparison") +
theme(legend.title = element_blank())
In this iteration I altered the aesthetic property by adding hover text and using plotly for additional user interface. While there is now more data available upon inspection, the initial view of the graph is still too complex. I have also reduced clustering in the aesthetic property by changing the dotted lines to a simpler solid.
library(plotly)
##
## 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(
ggplot(nfl_data, aes(x=Season, y=Rate, group=Player, color=Player,
text=paste("Passing Yards: ", Yds, "<br>",
"Interceptions: ", Int, "<br>",
"Touchdowns: ", TD))) +
geom_line() +
geom_point()
) %>%
layout(title = 'QB Stats Over Seasons',
xaxis = list(title = 'Year in NFL'),
yaxis = list(title = 'Passer rating'))
In this next iteration I altered the aesthetic property by changing the axis ranges, titles, and shapes of data points. The season ranges now take into account the fact Mahomes has only been in the NFL for 7 years. The shape alterations do not appear to have any positive affect. The hover text now does not repeat player name twice, but Yds is listed twice as well are the player names in the legend.
nfl_data_filtered <- nfl_data %>%
filter(Season %in% 1:7)
p <- plot_ly(data = nfl_data_filtered, x = ~Season, y = ~Rate, color = ~Player, type = 'scatter', mode = 'lines+markers', marker = list(symbol = 'star')) %>%
layout(
title = "Passer Rating by Season",
xaxis = list(title = "Season", dtick = 1),
yaxis = list(title = "Passer Rating", tickvals = c(40, 60, 80, 100, 120, 140))
) %>%
add_trace(
text = ~paste("<br>Yds: ", Yds, "<br>TD: ", TD, "<br>Int: ", Int),
hoverinfo = "text+name",
hovertemplate = paste("Season: %{x}<br>Passer Rating: %{y}<br>Yds: %{text}<extra>%{data.name}</extra>")
)
p
Here I have altered the aesthetic property by color coding the players to the teams they played for, making the visualization far more intuitive. I have also cleaned up issues of repeat text anywhere, and I have spelled out Yds, TD and Int to include the full words for less knowledgeable viewers.
My plot follows the design principles we have learned in class by focusing on effective presentation of the data, clarity, and engagement. The display as a stacked line graph for quarterbacks’ first 7 seasons is a simple way to draw comparisons across the category versus the initial bar graph. Additionally, the interactive elements allow for a more in-depth exploration of the data without compromising clarity.
The plot clearly and quickly conveys my message that Mahomes is the best of the 4 quarterbacks (in passer rating for the first 7 seasons). He wins the passer rating category in 5 out of the 7 years.
colors <- setNames(c("#0A2342", "#FFB612", "#FB4F14", "#B3995D"), c("Brady", "Mahomes", "Manning", "Montana"))
p <- plot_ly(data = nfl_data_filtered, x = ~Season, y = ~Rate,
color = ~Player, colors = colors, type = 'scatter', mode = 'lines+markers',
hoverinfo = 'text', hovertext = ~paste("Passer Rating: ", Rate, "<br>Yards: ", Yds, "<br>Touchdowns: ", TD, "<br>Interceptions: ", Int),
showlegend = TRUE) %>%
layout(
title = "Passer Rating by Season",
xaxis = list(title = "Season", dtick = 1),
yaxis = list(title = "Passer Rating", tickvals = c(40, 60, 80, 100, 120, 140)),
legend = list(orientation = 'v', x = 1.05, y = 0.5, xanchor = 'left', yanchor = 'middle')
)
p
Finally I have decided that the hover text information is unnecessary, as passer rating already takes TDs, Ints and Yds into account when the metric is calculated. Therefore, I figured it would be useful to add an animated aesthetic property which shows how passer ratings changed over the first 7 seasons for each quarterback.
library(gganimate)
nfl_data_filtered <- nfl_data_filtered %>%
mutate(Rate = as.numeric(as.character(Rate)))
colors <- setNames(c("#0A2342", "#FFB612", "#FB4F14", "#B3995D"), c("Brady", "Mahomes", "Manning", "Montana"))
p <- ggplot(nfl_data_filtered, aes(x = Season, y = Rate, group = Player, color = Player)) +
geom_line() +
geom_point() +
scale_color_manual(values = colors) +
labs(title = "Passer Rating for First 7 Seasons", x = "Season", y = "Passer Rating") +
theme_minimal() +
theme(legend.title = element_blank(),
legend.position = "right",
legend.justification = "top",
legend.margin = margin(t = 0, unit = "mm"),
plot.margin = unit(c(1, 3, 1, 1), "lines")) +
scale_y_continuous(breaks = seq(40, 140, by = 20)) +
scale_x_continuous(breaks = unique(nfl_data_filtered$Season))
p+transition_reveal(Season)
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?