Interactive Ternary Plots with Plotly | by Soner Yıldırım | Towards Data Science

Plotly Python (plotly.py) is an open-source plotting library built on plotly javascript (plotly.js). One of the things I like about plotly.py is that it offers a high-level API (plotly express) and a low level API (graph objects) to create visualizations. With plotly express, we can create a dynamic and informative plot with very few lines of code. On the other hand, we need to write more code with graph objects but have more control over what we create.
In this post, we will create ternary plots using plotly express. Ternary plots depict the ratios of three variables by positioning the data points in a triangle accordingly. It gives us an overview whether the observations lean towards a certain variable. Each corner of the triangle is labelled with one variable. Thus, we can only compare three variables.
Consider we are evaluating three car brands on lots of measurements. Each brand has a rating on each measurement. By plotting these measurements on a ternary plot, we get an idea if one brand is more dominant than others. For instance, one brand might be prominent in terms of safety related measures.
I could not find a dataset that compares car brands in many different measures but I was able to find an interesting one which is adataset that has RGB values of colors. Each color is made up of a combination of red, green, and blue (RGB). The colors change according to the ratios of these three main colors.
The dataset that is available here on data.world website includes RGB values for 746 different colors. I did not even know if some of those colors existed. There are some weird color names such as “Alizarin crimson”, “Bazaar”, and “Charcoal”. We will use ternary plot to get an overview about the RGB components of this wide range of colors.
Let’s first read the dataset into a pandas dataframe and take a look at it.
import numpy as npimport pandas as pddf = pd.read_csv("/content/colorhexa_com.csv")print(df.shape)df.head()
For now, I’m only interested in the name of the color and RGB components so I will only take those columns and change the names of colors.
new_cols = {'Red (8 bit)':'Red', 'Green (8 bit)':'Green', 'Blue (8 bit)':'Blue'}df.rename(columns=new_cols, inplace=True)df = df[['Name', 'Red', 'Green', 'Blue']]df.head()
I also want to add a marker for each color name that indicates the RGB color which contributes most. I will use nested loops but feel free to try out your own way.
winners = []for i in range(len(df)):  if df.iloc[i,1] > df.iloc[i,2] and df.iloc[i,1] > df.iloc[i,3]:    winner = "Red"  elif df.iloc[i,2] > df.iloc[i,3]:    winner = "Green"  else:    winner = "Blue"  winners.append(winner)df['winner'] = winnersdf.head()
Let’s first create a simple ternary plot that positions each color according to RGB component values. We will use plotly express which is the high-level API of plotly python.
import plotly.express as pxfig = px.scatter_ternary(df, a="Red", b="Green", c="Blue", hover_name="Name")fig.show()
Most of the colors are around the center of triangle but there is a slight incline towards red. We also have colors located on the edges of triangle. Those colors only include two of three RGB colors. Not surprisingly, the colors on the corners contain only one component. For instance, navy blue has only blue component.
We pass the “Name” column hover_name parameter which allow to see the name of the color when hovering on a point.
We can make the plot look better by using color parameter. A title would be nice to have as well.
fig = px.scatter_ternary(df, a="Red", b="Green", c="Blue", hover_name="Name",color="winner", color_discrete_map = {"Blue": "blue", "Green": "green", "Red":"red"},title="RGB Distribution of Colors")fig.show()
The dots representing the data points (rows in the dataframe) have equal size but plotly allows to add informative power to the size of the dots as well. Let’s use one of the built-in datasets to show how the size parameter can be used.
df_election = px.data.election()print(df_election.shape)df_election.head()
This election datasets contain the number of votes received by three candidates in 58 districts. “Total” column includes the total number of votes in the district which I think is proportional to the population of the district. We can pass the “total” column to the size parameter and see a particular candidate are winning more of the bigger districts.
fig = px.scatter_ternary(df_election, a="Joly", b="Coderre", c="Bergeron",hover_name="district",color="winner", size="total", size_max=15,title="District Election Results")fig.show()
“Coderre” leads by far. The districts won by “Joly” have relatively smaller sizes. One interesting thing that I realize is that the districts won by Coderre lean towards Joly more than they lean towards Bergeron. When we hover on data points, we see that Joly is usually the second candidate. Thus, Joly might have received more votes although the districts won by Joly seem smaller. Let’s check by counting the total number of votes for each candidate.
print("Total number of votes for Coderre is {}".format(df_election.Coderre.sum()))print("Total number of votes for Bergeron is {}".format(df_election.Bergeron.sum()))print("Total number of votes for Joly is {}".format(df_election.Joly.sum()))
Yes! Joly has more votes than Bergeron.
In addition to the size, we can also use the shape of data points to deliver information. For instance, the “result” column takes two values:
We can pass this column as an argument to the symbol parameter.
fig = px.scatter_ternary(df_election, a="Joly", b="Coderre", c="Bergeron",hover_name="district",color="winner", size="total", size_max=15,title="District Election Results", symbol="result")fig.show()
We have an idea if a particular candidate wins by majority or plurality.
We have covered ternary plots with plotly. Of course, this is just a little of what can be done with this amazing library. There are many other plot types that we can dynamically create with plotly. Its syntax is easy to understand as well. I will try to cover more complex plots in the upcoming posts. You can also check the plotly documentation which I think is well-documented with many different examples. Just like any other topic, the best way to get familiar with plotly is to practice. Thus, I suggest creating lots of plots to sharpen your skills.
Thank you for reading. Please let me know if you have any feedback.