Visualizing NFL Free Agency as a Node Network
The first wave of NFL games is in the books. Le’Veon Bell is a Jet. Odell Beckham Jr. had to turn over his blue uniform for a brown (Browns) one. How many players did your favorite team lose this offseason? Who did they pick up? Where’s everybody going?
Every year, hundreds of players switch teams and sign big contracts in a mass exodus called NFL Free Agency. If you’re just tuning in for the beginning of the NFL season, your team might look very different from when you last saw them.
How do you make sense of player movement across teams and see the whole picture? I wondered the same thing, so I created a node network to visualize all of NFL free agency on one page.
Demo: https://nfl-fa-2019.surge.sh/
The NFL offseason is an integral retrospective of a team’s performance when they determine how to rebuild or retool their rosters within the constraints of the salary cap. During this phase, general managers seek talent in the NFL draft and in free agency. Free agents are players whose contracts have expired and, as such, are free to sign with any team.
Currently, to understand NFL free agency you must sift monotonously through tabulated records of players. For example, the 2019 free agency table from OverTheCap lists each player along with their old and new teams. Finding information for a particular player is easy, but understanding why a team might have made certain decisions is lost in the rows and columns.
I wanted to know how many players the Carolina Panthers signed this offseason, how many they lost, and how much money they spent on their newly signed players. I wanted to see which teams are attracting top talent and which teams are losing it. With each player acquisition, I wanted to evaluate whether or not a team improved upon their weaknesses from last season. If a team struggled defensively, I wanted to know whether or not they looked to improve their defense by signing defensive linemen, safeties, or linebackers. Most importantly, I wanted to discover new insights and relationships hidden amongst the rigidity of the table structure above.
Essentially it boils down to one question: What is the best way to view all types of player movement and easily drill down on specific player information?
My answer is to visualize free agency as a node network. A node network is a direct representation of a graph, which is made up of edges (links) and vertices (nodes). Links are connections between nodes to show their respective relationships. This visualization is very tempting since it shows the flow of all players between teams and encodes various information into the size of the nodes and colors of the links.
But a node network comes with its own drawbacks. Searching for a particular set of nodes becomes difficult with large amounts of data. The network is often cluttered and requires a great deal of tedious tweaking and optimization, and encoding that much information makes a lot of assumptions about the audience, especially one that is not familiar with NFL lingo or semantics. However, it was still worth a shot.
I began by scraping data from OverTheCap (as shown in the table referenced earlier). I used Python, Pandas, and Beautiful Soup to assemble a graph structure with nodes and edges. Nodes were assembled by iterating through player and team information, and an edge was created for a player’s 2018 team and their 2019 team. If a player stayed on the same team, only one edge was added. Player details like position, name, and APY (average per year) were recorded. APY is the dollar amount a player will cost toward the salary cap for that year. At the time of this article, 1190 players were scraped — 598 signed and 592 unsigned.
After data collection I prepped a few players for visualizing to see what a potential node network might look like. I mainly used d3 for creating interactions and assembling my force diagram. I used Vue and Vuetify to lay out my application and set breakpoints for mobile devices respectively. Figuring out the right way to encode information was difficult, but after several iterations and feedback I was able to construct meaningful nodes and edges.
Players are nodes represented by white circles. A label for their abbreviated position is centered inside. The size of the player node is equivalent to the square root of the player’s APY. On hover, a tooltip pops up that displays the player’s name, position, and salary, along with the teams that the player is associated with. In this case it’s Russell Wilson, quarterback (QB) for the Seattle Seahawks. The size of a player node is important for the user to be able to distinguish highest-paid players in the league.
Teams are also represented as nodes with a square blue background and their logo in the center. Hovering over a team highlights all player activity for that team. This is useful when comparing one team’s free agency decisions with another’s.
There are three types of edges to describe player movement. Red lines describe a player leaving a team for another. Yellow lines describe a player joining a new team. And blue lines are for players who chose to re-sign with the same team. For example, when comparing the Eagles’ and Jaguars’ QB nodes, the bigger player node, quarterback Carson Wentz, re-signed with the Eagles for a massive contract represented by a blue line. The smaller node is quarterback Nick Foles, who left the Eagles (red line) to become the new quarterback for the Jaguars (yellow line). This micro-relationship might get lost in the weeds in a table, but not in a node network. Being able to visualize these interactions from team to team helps articulate a team’s strategy behind the scenes.
In my first major iteration, I had a proof of concept of what NFL free agency might look like, but my viz was heavily cluttered, unfit for mobile devices, and made a lot of assumptions about my audience.
I originally used a light background, red and green colors, and even included dashed lines to describe players leaving and joining new teams. The result was a heavily cluttered structure because of redundant encodings, limited user interaction, and color choices that didn’t add any value. Hovering over players and teams to highlight their relationships did not blur out the rest of the network, which made it tough for the user to focus on a particular interaction. I also visualized only signed free agents, and not unsigned players trying to find a new team. Knowing these unsigned free agents is important for teams, who need to be aware of which players are available. On mobile devices, the network would be heavily zoomed in, and without a legend, users unfamiliar with the NFL would have a hard time understanding what they were looking at.
After receiving feedback on the first iteration, my biggest area of focus was to create a filtering system so that users could reduce the clutter and hone in on specific traits. Zooming in and out of the graph wasn’t enough to drill down on nodes.
I decided to create a legend that acted as a control panel for the entire visualization. Toggling the player-movement circles would turn off respective edges. This would allow the user, for example, to see only players who were leaving teams. A slider was added to filter player nodes by their salary. On a mobile device, this legend would take a huge chunk of real estate, which is why it was important to have a button that could enable and disable the legend. These controls enable the user to guide their exploration by filtering out players under a certain salary or to look at specific player-movement trends.
Along with the added interactions, I made color changes, added a darker background, changed fonts, and polished other aesthetics. Previously, I wasn’t showing unsigned free agents because they weren’t assigned to any team. But by adding them to the graph, the d3 algorithm automatically put them on the outside because they didn’t have any edges. Hence the constellation-looking structure with unsigned free agents on the outside looking in. During the offseason, with regular updates to the visualization, it was interesting to see which players were left on the board as teams quickly snagged top talent.
While the bulk of the work has been completed, my focus for next offseason is to add a search feature to find specific teams and players, the ability to load different years, and create a way to visualize a team’s total cap space. Another key area of focus is to provide more information about players and teams. This will help users differentiate the quality of free agents based on a team’s needs.
The current state of the graph shows something we haven’t seen before—the entire state of the 2019 NFL free agency on a single page! With plenty of interactions for the user to draw insights, the user can contextually hover from team to team and compare different types of player movement. It’s easier for a user to hover over encoded information they find interesting than it is to run manual searches between tables, and clicking for specific information. Check out the live site for yourself here!
Beyond the NFL however, this type of visualization could be useful not just for other sports like the NBA, but also in entirely disparate fields like human resources to track employment across departments or even in website routing to track users’ navigation patterns.
I hope you all enjoyed reading about my process and learning why I designed my viz the way I did. If you have suggestions, ideas, or want to collaborate, feel free to reach out to me or drop some feedback on my website!
Demo: https://nfl-fa-2019.surge.sh/
Github Link: https://github.com/adv1996/nfl-free-agency-graph