Plotly Fundamentals -
3D Plots

In this chapter of our Plotly tutorial we will look at a family of charts that might be considered a little bit fringe and mostly used in scientific applications when displaying three dimensional data. Nevertheless, there are some pretty cool applications such as drawing the surface of landscapes, lower dimensional projections and others which make it worth it to explore them. You probably know how it goes by now so lets start importing some libraries. Here we will also use the numpy library which contains many useful functions for scientific computing applications.

import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.express as px

For the first example we will once again use the iris data set provided by the Plotly Express package.

iris = px.data.iris()
iris.head()
sepal_length sepal_width petal_length petal_width species species_id
0 5.1 3.5 1.4 0.2 setosa 1
1 4.9 3.0 1.4 0.2 setosa 1
2 4.7 3.2 1.3 0.2 setosa 1
3 4.6 3.1 1.5 0.2 setosa 1
4 5.0 3.6 1.4 0.2 setosa 1

Conveniently, everything we have been using including colouring of certain attributes and other features work out of the box for three dimensional scatters too. The only need to exchange the standard scatter function with scatter_3d and complement our x and y values with a z value and voila, a nice 3d scatter of our flower data which once again reconfirms what we discovered already in two dimensions, i.e. that flowers of the Setosa species can be easily separated from the others.

fig = px.scatter_3d(iris, x='sepal_length', y='sepal_width', z='petal_width',
              color='species', height = 800)
fig.show()

For those of you that would like to cheat in a fourth dimension you can also add a series of continuous values to the color attribute to achieve gradient colouring of the data points. To still have the categorial values displayed you can add differently shaped markers by providing the values to the symbol attribute. Finally, adding something more to our bag of tricks, we can use the update_layout function to position the legend in the top left corner of the chart which makes the chart much more clean.

fig = px.scatter_3d(iris, x='sepal_length', y='sepal_width', z='petal_width',
              color='petal_length',symbol = 'species', height = 800)

fig.update_layout(legend=dict(
    yanchor="top",
    y=0.99,
    xanchor="left",
    x=0.01
))

fig.show()

Going away from the popular scatter graph we will now explore a different way to present three dimensional data with surface plots. To do this we have to leave the express functions aside and create a figure object with graph objects.

For starters, we will create a function and a x/y grid against which the function is evaluated. Thereafter, we can pass the obtained values to the Surface function. The numpy function meshgrid conveniently helps to set up the grid of function values.

def f(x, y):
    return np.sin(np.sqrt(x ** 2 + y ** 2))

x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
z = f(X, Y)

fig = go.Figure(data=[go.Surface(z=z)])
fig.update_layout(height = 800)
fig.show()

In the following example we have added some additional styling by making the chart a bit opaque and at the same time add contour lines using the contours_z attribute in combination with the update_traces function. This allows much easier inspection of the function when rotating the chart around.

fig = go.Figure(data=[go.Surface(z=z, opacity =0.5)])
fig.update_traces(contours_z=dict(show=True, project_z=True))
fig.update_layout(height = 800)
fig.show()

Finally, we can also use line plots in three dimensions with the line_3d function in plotly express. We are using the gapminder dataset as it is more meaningful than our trusted iris dataset. It contains some socio-economic data indexed by a year column. We will start looking at French gdp and population size across time.

france = px.data.gapminder()
france = france[france['country'] == 'France']
france.head()
country continent year lifeExp pop gdpPercap iso_alpha iso_num
528 France Europe 1952 67.41 42459667 7029.809327 FRA 250
529 France Europe 1957 68.93 44310863 8662.834898 FRA 250
530 France Europe 1962 70.51 47124000 10560.485530 FRA 250
531 France Europe 1967 71.55 49569000 12999.917660 FRA 250
532 France Europe 1972 72.38 51732000 16107.191710 FRA 250
fig = px.line_3d(france, x="gdpPercap", y="pop", z="year", height = 800)
fig.show()

Once again, you can dump a larger dataframe into your function call and color code the series based on a classification. In this case we are using the countries as class inputs. 

europe = px.data.gapminder()
europe = europe[europe['continent'] == 'Europe']
europe.head()

fig = px.line_3d(europe, x="gdpPercap", y="pop", z="year", color = 'country', height = 800)
fig.show()

This concludes our exploration of three dimensional data display. No worries though, there is still plenty unchartered territory we need to visit. Therefore, read on and learn how to easily create pretty, responsive map plots in the upcoming chapter or our tutorial series.

fistofgeek.com

coding - data science - finance

Get Connected