Luke Stanke

Data Science – Analytics – Psychometrics – Applied Statistics

NFL Analytical MVP 2016

Polar Clock in Tableau

About/How to

If you’ve read anything about data visualization you probably have heard of Mike Bostock. He was the genius behind many great New York Times graphics and created D3.js – one of the best data visualization tools available. Recently he offered updated versions of his polar clocks, which were originally inspired by Gabriel Mak’s PolarClock screen saver. Seeing this, I challenged myself to build the clock in Tableau.

Bostock's Polar Clock II

Not knowing how to do this, I decided to build a versatile dataset that could handle the job. The dataset has 606 rows, these rows are broken out in 202 row groups for hours, minutes, and seconds. Within those 202 rows, 201 are devoted to the trail/tail and 1 row is devoted to the main time location. Each row has 6 columns: 1) an index column; 2) a degrees column where row 201 for a given group is equal to 90; 3) a radius column – all values set to 1; 4) a size column – which I intended to use for setting the width of the lines, a factor column; 5) to indicate if its the main time point or the tail; 6) and segment – either hour, minute, or second.

Polar Clock Data Screen Shot

Once loaded into Tableau. we just need to figure out the current time. This can be done with the NOW() function. Since this information is possible, we now need to get the current hour, minute, or second. Once again, Tableau has a great function called DATEPART() that can pull any part of a date out from a string. Here is how you do it for minutes:

//  Get current hour
DATEPART('minute', NOW())

After getting this information, we just need to get this information on the clock in the correct position — for the sake of this tutorial we will use degrees. On a 12 hour clock, 45 minutes will be positioned 75% of the way around the clock — or 270º from the start point. The degrees in hours is a bit more complicated — though not much, since the clock handles 12 hours, but a day is 24. I just used the modulo % function which returns the remainder in a division problem. Here are each of the variables we’ll use for further analysis later

Hour
// Hours in degrees
(((DATEPART('hour', NOW()) + (DATEPART('minute', NOW())/60)) % 12)/12)*360

[Minute]
// Minutes in degrees
(DATEPART('minute',NOW())/60)*360

[Second]
// Seconds in degrees
(DATEPART('second',NOW())/60)*360

Generally once we know this, its just a bit of geometry to identify the x and y coordinates. Here’s the general formula for finding x and y coordinates given radius and degrees:

[x]
//  Get x coordinates from degrees and radius.
[radius]*SIN(RADIANS([degrees]))

[y]
//  Get y coordinates from degrees and radius.
[radius]*COS(RADIANS([degrees]))

Since we have all of the information about hours, minutes, and seconds in a column called [segment], we need to specify the coordinates for hours minutes and seconds in one column using the CASE() function. I also want to give hours minutes and seconds each a different radius so they don’t overlap on my clock. I’m going to hard code hours to a radius of 0.8, minutes to 1.0, and seconds to 1.2. When I make my clock this will put hours on the innermost ring and seconds on the outermost ring. Here’s the code only for the x coordinates:

[X]
//  X coordinates from time.
CASE [segment]
WHEN 'hour' THEN .8*SIN(RADIANS([Hour]))
WHEN 'minute' THEN SIN(RADIANS([Minute]))
WHEN 'second' THEN 1.2*SIN(RADIANS([Second]))
END

If I create a visual using this data you’ll see it’s not anything special.

Polar Clock - Incomplete Pt 1

I really need to add the tail to make it interesting. I can do this by modifying the code just slightly.

[X]
//  X coordinates from time with a tail.
CASE [segment]
WHEN 'hour' THEN .8*SIN(RADIANS([Hour]-([Deg])))
WHEN 'minute' THEN SIN(RADIANS([Minute]-([Deg])))
WHEN 'second' THEN 1.2*SIN(RADIANS([Second]-([Deg])))
END

Using this function, we can begin to have something that resembles the polar clock.

Tableau Polar Clock - Incomplete part 2

This could be good enough, but we want to create a parameter to control the tail length — Let’s just call the parameter [Length] to make it easier — and set the range from 0.1 to 2. We just need to add this to our [x] variable:

[X]
//  X coordinates from time with a tail.
CASE [segment]
WHEN 'hour' THEN .8*SIN(RADIANS([Hour]-([Deg]*2*[Length])))
WHEN 'minute' THEN SIN(RADIANS([Minute]-([Deg]*2*[Length])))
WHEN 'second' THEN 1.2*SIN(RADIANS([Second]-([Deg]*2*[Length])))
END

To make things easier, let’s also add a background to the chart. Here is the image i used:

Polar Clock Background

If you set the min and max values to -1.5 and 1.5 for x and y it produces this chart:

Tableau Polar Clock - Incomplete Pt. 3

One last thing we want to add: a parameter to change the line width of the tails. We want it to either be tapered or blunt. So let’s create a [Taper] parameter where the values range from 0 to 1. Then we can write a function that uses the taper parameter:

[varied taper]
// Varies line width
([Taper]*[Size])+((1-[Taper])*(1-([Index]/202)))

Once I have all this information, I can create a polar clock with parameters to control the tail. I’ll also throw in some additional styling.

This is excellent, except one thing — the clock only has the correct time when you load it. I want it to tick. Luckily, you can do this by using Tableau’s javascript API. UPDATE: I’m providing the API script written by Allan Walker and Chris DeMartini below — Here is the article that provides some additional guidance.

  var viz, one, workbooka, activeSheet, Worksheet, worksheet;

  var onePh = document.getElementById("tableauViz1");


  var oneUrl = "https://public.tableau.com/views/PolarClock/PolarClock?:showVizHome=no&:display_spinner=no&:jsdebug=n&:embed=y&:display_overlay=no&:display_static_image=no&:animate_transition=yes"; //Polar Clock

  var oneOptions = {

      width: "105%",
      height: "112%",
      hideTabs: true,
      hideToolbar: true,

  onFirstInteractive: function () {
          }
        };

  viz1 = new tableauSoftware.Viz(onePh, oneUrl, oneOptions);
  ;

  function clock() {
    viz1.refreshDataAsync();
    setTimeout(clock, 500);
  }

  clock();

Adding this to my page — and doing some stuff to make it happen in WordPress — produced this as my final result:

Who is the best running back?

Who should be the NFL MVP

It’s the end of the National Football League regular season tomorrow. With that, comes talk about who the best player — the MVP — will be. Since 2000, the MVP award has been won by 11 times by quarterbacks and 4 times by running backs. In fact, since the award has been given out only two defensive players — Alan Page in 1971 and Lawrence Taylor in 1986 have ever won MVP. The award has been given out to a special teams player just once — to Mark Moseley in the strike-shortened 1982 season. His recognition is a bit of an oddity, and some suggest he might not have even been the best kicker that year.

It’s easy to suggest what Most Valuable means — a player that has contributed the most to his team’s success — but it’s a lot harder to quantify that. It’s what smart statisticians that work for big sports companies work on all the time and think about with more data than I have access to, but I’m going to give it a shot. Using play-by-play data from Armchair Analysis, I created a model that gives the chances of winning of a game given the context of the games — things like time to play in the game, down, distance to go, distance from goal, and the difference in score.

Using this information I could then figure out what the chances of team are to win at any given point in the game. Take this situation: Let’s pretend Aaron Rodgers has the ball on his opponents 40 yard line. It’s 2nd and 7 yards to go with 7:50 remaining in the game and the Packers are down by four. In this situation, Rodgers and the Packers have a 45.92% chance to win the game. On the next play he is forced to run, and he gains 34 yards. The new odds of winning the game for the packers are 50.02%. This mean Rodgers contributed .051 points to his team’s chances of winning. We can figure this out for every player on every play. And then we can add it all up to figure out who’s the MVP.

So who is the MVP?

NFL Box Scores

I used to go to an awesome site to get important/cool data for playing fantasy football — Advanced Football Analytics — but it was bought by ESPN and the secret sauce/important information was no longer available to me. I had a few options: 1) cry like a baby; 2) find a different site; 3) find the data and develop my own analytics. I choose to create my own thing. I’ve developed a boxscore data tool in Tableau. It’s still early on but here’s what it looks like so far: