Pie & Donut Charts with Plotly. Why & How | by Darío Weitz | Towards Data Science

WHY: Pie Charts (PCs) are used to display parts of a whole of mutually exclusive and not overlapping categories. The conceptual idea is not to make a comparison between the categories but to show the percentage or proportion of each category with respect to the total. This type of chart should not be used for Correlation, Deviation or Distribution analysis.
HOW: PCs are circular charts divided into slices-like sectors. The full circle represents the whole (100%) while the slices represent the parts. Each of the parts must be correctly labeled and preferably include the numerical value corresponding to the percentage of the sector. Slices (segments, sectors, wedges) cannot overlap (mutually exclusive). They must consistently add up to 100%.
PCs encode the corresponding numerical values with two visual attributes: 1.-length of each slice along the perimeter; 2.-area of each slice.
Storytelling: PCs are widely used in finance, business, journalism, and education to show percentages or proportions among a large variety of categories including budgets, sales, rate of unemployment, segments of a population, academic performances, or answers to a survey. They express a message of whole-part relationships through the area of each slice and/or the length of each slice along the pie’s perimeter.
Their use as a Data Visualization technique is the subject of deep controversy: on the one hand, those visual attributes are not easy to decode; on the other hand, audiences are very familiar with the simple aesthetics of the pie charts. What is beyond dispute is that they are hard to read when there are too many slices.
Some Warnings
· Always check that the whole is 100%, that the whole makes clear sense to the audience, and that the categories are mutually exclusive. For example, these requirements are not always verified in survey results.
· Always include annotations and percentages to describe the content.
· PCs should not be used for accurate comparisons, when differences between categories are minor, or for trends or patterns.
· Try to not use more than six or seven slices. They are not only hard to read but also there are too many legends.
· If you have numerous small sectors that are difficult to read, try to combine them into a single sector with a legend appropriate to the new situation and with a neutral color.
· Avoid all 3D effects. Although they are aesthetically pleasing, they introduce distortion and hinders seriously the interpretation of the message.
Alternative 1: Donut Charts (Doughnut Charts)
They are absolutely equivalents to pie charts (they display parts of a whole of mutually exclusive and not overlapping categories), with the only difference being a blank space (a hole) in the center of the chart where some kind of additional information is indicated to enhance the storytelling.
Now it is not possible to make a comparison of areas, but the numerical values of the sectors are encoded only by means of arc lengths along the perimeter of the circle.
Its use is justified when the information in the center allows gaining space and thus reducing the total space generated by the chart. For example, the legends corresponding to each sector can be indicated in the hole of the donut. Of course, this gain in space must outweigh the new difficulty generated by having fewer visual attributes.
Alternative 2: Segment Separation
The message can be reinforced by separating one or a few segments from the original pie. You can put the entire pie apart, or just highlight an individual slice depending on the narrative. Be aware that this visual separation produces a distortion in the chart that may make the message difficult to interpret.
Pie Charts & Alternatives with Plotly
Plotly, a technical computing company located in Montreal, Canada, launched in 2019 Plotly Express (PE), a new high-level Python visualization library. PE includes functions to plot standard charts with a single function call.
Plotly also provides a module named plotly.graph_objects which contains a hierarchy of Python classes. Figure, a primary class, has a data attribute that allows to create and display graphical figures in a relatively quick and easy way.
Our data refer to Population Economically Active in the Argentine Republic in 2017. We are going to show with a pie chart the percentages corresponding to four groups of the economically active population according to the type of pressure on the labor market. These four groups are named: 1.-’employed’; 2.-’unemployed’; 3.-’underemployed job seekers’; 4.-’underemployed non-job seekers’.
For the pie charts in this article, the Plotly Express function is px.pie, and the corresponding parameters are: data_frame, the first parameter, corresponds to the sectors of the pie; values sets numerical values associated to sectors; names sets the labels for the sectors; color assign hues to sectors.
This is the code for the pie chart in Figure 1 (above):
import plotly.express as pxlabels = ['employed', 'unemployed',            'underemployed job seekers',           'underemployed non-job seekers']values = [72.8, 7.2, 14.7, 5.3]fig1 = px.pie(labels, values = values, names = labels)fig1.show()
We considered it convenient to change the default colors for others that would improve the message. For such purpose, we used the parameter color_discrete_map and we obtained Figure number 2.
fig2 = px.pie(labels, values = values,              names = labels, color = labels,              color_discrete_map = {'employed':'blue',                                     'unemployed': 'red',                            'underemployed job seekers':'lightblue',                            'underemployed non-job seekers':'orange'             })fig2.show()
Next, we add a title and a hoover tooltip (Fig.3):
fig3 = px.pie(labels, values = values,              names = labels, color = labels,              color_discrete_map = {'employed':'blue',                                     'unemployed': 'red',                            'underemployed job seekers':'lightblue',                            'underemployed non-job seekers':'orange'             })fig3.update_traces(title = 'Population Economically Active',                   title_font = dict(size=25,family='Verdana',                                      color='darkred'),                   hoverinfo='label+percent',                   textinfo='percent', textfont_size=20)fig3.show()
Let’s see how the message is conveyed by a donut chart. We included the hole parameter to set the fraction of the radius to cut out of the pie.
fig4 = px.pie(labels, values = values, hole = 0.4,              names = labels, color = labels,              title = 'Population Economically Active',              color_discrete_map = {'employed':'blue',                                     'unemployed': 'red',                            'underemployed job seekers':'lightblue',                            'underemployed non-job seekers':'orange'             })fig4.update_traces(                   title_font = dict(size=25,family='Verdana',                                      color='darkred'),                   hoverinfo='label+percent',                   textinfo='percent', textfont_size=20)fig4.show()
We are interested in what the chart looks like with a separate segment, but there is a drawback: Plotly Express does not provide a parameter for that task. Therefore, we have to resort to plotly.graph_objects.
For the following donut charts in this article, the plotly.graph_objects function is data = go.Pie() and the corresponding parameters are: values; labels; hole; marker_colors.
import plotly.graph_objects as gocolors = ['blue','red','lightblue','orange']fig5 = go.Figure(data = go.Pie(values = values,                           labels = labels, hole = 0.4,                          title = 'Population Economically Active',                          marker_colors = colors                 ))fig5.update_traces(                   title_font=dict(size=25,family='Verdana',                                    color='darkred'),                                   hoverinfo='label+percent',                                   textinfo='percent',                                    textfont_size=20,                   )fig5.show()
As can be seen, we have a problem: the title has appeared in the hole. To solve it, we added an annotation in the hole.
fig6 = go.Figure(data = go.Pie(values = values,                                labels = labels, hole = 0.4,                               marker_colors = colors ))fig6.update_traces(hoverinfo='label+percent',                   textinfo='percent', textfont_size=20)fig6.update_layout(                   title_text = 'Population Economically Active',                   title_font = dict(size=25,family='Verdana',                                      color='darkred'))fig6.add_annotation(x= 0.5, y = 0.5,                    text = 'Year 2017',                    font = dict(size=20,family='Verdana',                                 color='black'),                    showarrow = False)fig6.show()
Let’s see if the message is reinforced by separating one segment from the original chart. We set values for pull, a list to define which slices are pull out from the center and to what extent.
fig7 = go.Figure(data = go.Pie(values = values,                                labels = labels, hole = 0.4,                               pull = [0,0.25,0,0],                               marker_colors = colors ))fig7.update_traces(hoverinfo='label+percent',                   textinfo='percent', textfont_size=20)fig7.update_layout(                   title_text = 'Population Economically Active',                   title_font = dict(size=25,family='Verdana',                                      color='darkred'))fig7.add_annotation(x= 0.5, y = 0.5,                    text = 'Year 2017',                    font = dict(size=20,family='Verdana',                                 color='black'),                    showarrow = False)fig7.show()
We leave it up to you to decide which chart (Fig.4, Fig.6, or Fig.7) provides the best storytelling.
If you find this article of interest, please read my previous (https://medium.com/@dar.wtz):
Lollipop & Dumbbell Charts with Plotly, Mean or Median?
towardsdatascience.com
Slope Charts, Why & How, Storytelling with Slopes