I made an application that lets you see how NBA trades connect over time. Inspired by this article.

The network

NBA trades are a deep, strange rabbit hole to jump into. Their history shows exchanges between teams that don’t exist anymore for players that even the most ardent fans have never heard of. Tales of woe reveal themselves in their records - star players earnestly exchanged for players history has forgotten, a future pick that would turn into a centerpiece bouncing around so many teams that missed out. Some truly bizarre decision-making begins to stand out.

The rabbit hole gets deeper than just a single trade though. A player’s arrival on a team can be traced back considerably further than their last immediate exchange. Viewing trades between players as a continuous set of connections, you can trace how player a “becomes” player d by checking out how a trade between player a and player b connects to a trade later on between player b and player c, which in turn connects to another trade later between player c and player d. Let’s ground this in an example with real players (the year of each trade is in parantheses).

Vince Carter → Eric Williams (2004) → Radoslav Nesterovic (2006) → Jermaine O’Neal (2008) → Shawn Marion (2009) → Hedo Turkoglu (2009) → Leandro Barbosa (2010) → Tomislav Zubcic as a 2012 second round pick (2012) → Luke Ridnour (2015)

This can be read as Vince Carter is exchanged in a trade for Eric Williams in 2004, who is then exchanged for Radoslav Nesterovic in a trade in 2006, etc. Here we have just one of the ways a trade involving Vince Carter connects to Luke Ridnour arriving to the Raptors years later. A series of connections that tells a long, strange story of front office decisions and shifting career paths. But can we find these types of connections for any player?

The scrape

Yes. The wonderful folks at the Pro Sports Transactions Database have comprehensive data on all professional basketball trades dating back to 1937. The scope of this analysis is limited to all trades since the NBA-ABA merger (November 16, 1976). With the help of R (in particular the rvest package), data is scraped from their website and use it to build a trade network. Further details and important caveats associated with the scraping are in the Appendix for those interested.

For some later analyses, player statistics data is scraped, again since the NBA-ABA merger, from the equally amazing Basketball Reference.

The visualizations

The resulting network can be poked, prodded, and visualized in the application created at svitkin.shinyapps.io/bball-trade-network/. In the app you can see trades evolve over time, watch players get drafted into the league or go in and out of free agency. Let’s get on with some examples! Check out those Vince Carter to Luke Ridnour connections again:

Vince Carter - Luke Ridnour Connections

Briefly contemplate this bizarre Lebron James and Luke Walton trade relationship:

Lebron James - Luke Walton Connection

Indulge my obsession with Eric Bledsoe (he’s the best), and check out his trade connections throughout the years:

Eric Bledsoe Connections

In the application, you can find more details of each trade by hovering over connections between players. Details on how paths in the trade network are created can be found in the Appendix.

The forrests

We can leverage properties of networks and our scraped player data from Basketball Reference to dig a bit deeper. In the article that inspired this whole plunge, the author describes the player Arturas Gudaitis as a Forrest Gump of trades. Someone involved in all these historic, landscape changing exchanges who no one has actually heard of or seen play much (in Gudaitis’s case, not at all). Players moved around as part of the labyrinthian calculations front offices make to work within the salary cap.

How can we find these Forrest Gumps? One way is to look at the ratio of minutes played per game (in the regular season) for a player compared to the number of players they were exchanged for in trades, the idea being to identify players who don’t play very much but were involved in large trades quite a bit. However, a few data-related difficulties arise in any analysis connecting the network and player data. To connect the player trade data with the player statistics data, the datasets are matched by names. Unfortunately, no match is found for 362 out of the 2,257 players (16%) in the network. Additionally players with 0 minutes played (like Arturas Gudaitis) are not in the player statistics data and therefore not matched with the network. For the simple average minutes per career statistic, players’ minutes are aggregated as a weighted average of the minutes played per game, for a team in a season, and the number of games played for that team in that season.

With all that in mind, here are the top 5 players since the NBA-ABA merger who played the least and got traded the most (relatively) for the three categories of positions - guard, forward, center. Players can obviously change position over time, so to (possibly over)simplify things the first recorded position of the player in the data is used.



Choices made when scraping from Pro Sports Transactions Database:

  • Removed exchanges with future picks
  • Removed exchanges with non-agreements or non-exercised picks
  • Removed exchanges with unknown picks or unknown offer sheets
  • Removed exchanges where agreement to waive was involved
  • Removed exchanges where modification of pick was involved
  • When discrepancy with media guide pointed out, used information contained in Pro Sports Transaction Database instead of media guide

Path creation

The original data scraped from the Pro Sports Transactions Database, is a network of players where a connection exists if two players were exchanged in a trade at some point in time. However, to create the visualizations from the application, time and team must be taken into account. A path between any two players must have sequential connections involving the same teams and must uniformly go forward or backward in time.

Invalid date path:
player a → player b (2015) → player c (2014) → player d (2016)
Valid date path:
player a → player b (2015) → player c (2016) → player d (2017)

Invalid team path:
player a → player b (between Magic and Rockets) → player c (between Pacers and Knicks)
Valid team path:
player a → player b (between Magic and Rockets) → player c (between Rockets and Knicks)

Both team and time need to be correct for a path to be valid. To find valid paths, a breadth first search is used, where each connection being searched along the network is tested for date and team validity.

All code for the project can be found at https://github.com/svitkin/bball-trade-network.