A Quick Word on 3D and Map Projections
Quick caveat here, I know that 3 dimensional data viz can be a controversial subject. Before using the methodology below, make sure that it's correct for the analysis, data storytelling and audience you're supporting. Having said that, the problem with visualizing a round Earth on a flat map has always been a struggle. Tableau currently supports a WGS 84 Web Mercator projeciton, which is pretty standard across the board, but one of several different projections. Having said that, here we go with the methodology...
Let's create a Globe!
When I was creating this month's ThrowbackDataThursday data challenge, I brought the data into Tableau and created a really quick map. With the map background washed out and all layers removed, the data created a really interesting view of the UFO Sighting data. Below is a quick view filtered to the US, with the size denoting the duration of the UFO sighting.
I really like the simplicity of the map, but when I removed the filter and zoomed out, the view got distorted. I started doing some research about creating a globe in Tableau. I came across Ken Flerlage's 3D Star Map and Bora Beran's classic post on bringing 3D to Tableau. If you've not read those posts, I recommend taking a break to read those - the rest of this post will likely make more sense.
In an effort to create a globe with a very familiar feel, we'll use coastline data - with Latitudes and Longitudes extracted from a shapefile. If we plot this dataset in Tableau as is, we get the following.
With a dataset in hand, the first step in going 3D was taking the two 2D points I had - Latitude and Longitude - into 3D points - X, Y and Z. I found a great page on Mathworks detailing the formulas necessary to calculate Earth Centered/Earth Fixed points from Latitude and Longitude.
The calculations for X, Y and Z require a couple of helper calculations - the radius of the Earth at the surface point, and the geocentric latitude at mean sea level. The logic is pretty simple:
With the radius and geocentric latitude at mean sea level, we're ready to calculate our X,Y and Z points. Keep in mind that when we deal with latitude and longitude in Tableau's default format, the units for these are decimal degrees. This is important as we bring in the trigonometric functions that these calculated fields rely upon. In order for the viz to correctly render, we need to convert the degrees to radians. Similar to the X and Y calcs required to draw a circle in Tableau, we're leveraging Sine and Cosine. If you want a refresher on your Trig, check out Ken Flerlage's awesome blog post here.
Here are our calcs:
Once we've got these guys built, we can leverage the calculations that Ken modified from Bora. First, we need a few parameters. These will drive the orientation of our globe in our viz, as well as allow the user to rotate the globe. Create your Parameters as follows:
- [XY Angle] - Integer - Current Value: 100 - Range: 100 to 460 - Step size 10 (this allows for one rotation of the globe, with the Continental US front and center)
- [XZ Angle] - Integer - Current Value: 267 - Range: 0 to 360 (currently set at 267 to get the orientation "correct")
- [YZ Angle] - Integer - Current Value: 0 - Range: -360 to 360 (currently set at 0 to get the orientation "correct")
With these parameters and the calculations we built previously, we can construct our next set of calculations. These calculations are the magic that effectively take our 3D points and convert them back to 2D.
Now, assuming we've gotten all of our calculated fields written correctly, we can get vizzing. [y_rotated] goes to the Columns shelf as a dimension and [x_rotated] goes to the Rows shelf as a dimension. At this point, you're probably looking at a flat globe that is missing its depth. To fix this we need to take advantage of color. You can simply use your [z_rotated] on the color with a sequential color palette. Our model is leveraging a virtual XYZ coordinate system where negative [z_rotated] values are those that are "coming out of the screen." I've used this to ensure that my negative [z_rotated] values have the bright color, and the most positive values fade into the background. I've created a couple of custom palettes that work well for me in this space.
At this point, you should end up with something like this:
The animated GIF above was created from a screen recording where I clicked through the [XY Angle] parameter. I then sped up the video and converted to a GIF.
I know it's not the most standard data visualization, but if you come across a place where you can use it, I'd love to see the outcome! Below is my finished #ThrowbackDataThursday Viz. Hope you enjoy!