I am practising building a Pie Chart in Plotly Express using Python.
So, this is the Pie Chart that I made;
This chart was build from a file with two columns called
gender
with values of [0, 1, 2]
count_genders
with values of [total_count_0, total_count_1, total_count_2]
I am planning to add some description to those values; for instance
0 - female
1 - male
2 - undefined
This is where I am currently stuck.
If I remember correctly if you want to change a label in the legend (at least in Choropleth map), you could manipulate the ticks
located in colorscale
bar. By manipulating them, you could rename the label about the data. Thus I am wondering if you could do the same in Pie chart?
My current code for this graph:
import pandas as pd
import plotly.express as px
'''
Pandas DataFrame:
'''
users_genders = pd.DataFrame({'gender': {0: 0, 1: 1, 2: 2},
'count_genders': {0: 802420, 1: 246049, 2: 106}})
''' Pie Chart Viz '''
gender_distribution = px.pie(users_genders,
values='count_genders',
names='gender',
color_discrete_map={'0': 'blue',
'1': 'red',
'2': 'green'},
title='Gender Distribution <br>'
'between 2006-02-16 to 2014-02-20',
hole=0.35)
gender_distribution.update_traces(textposition='outside',
textinfo='percent+label',
marker=dict(line=dict(color='#000000',
width=4)),
pull=[0.05, 0, 0.03],
opacity=0.9,
# rotation=180
)
gender_distribution.update_layout(legend=dict({'traceorder': 'normal'}
# ticks='inside',
# tickvals=[0, 1, 2],
# ticktext=["0 - Female",
# "1 - Male",
# "2 - Undefined"],
# dtick=3
),
legend_title_text='User Genders')
gender_distribution.show()
I tried to add the ticks
in the update_layout
to no avail. It returns an error message about incorrect parameters. Would someone kindly help me fix this issue?
edit 1: In case I wasn't clear, I wanted to know if it's possible to modify the values displayed in the legend without changing the original values within the file. Many thanks for your time for those who are already kind enough to help me fix this issue!
edit 2: Add the imports and other prior details of the code, removing the Dropbox link.
If I'm understanding your question correctly, you'd like to change what's displayed in the legend without changing the names in your data source. There may be more elegant ways of doing this but I've put together a custom function newLegend(fig, newNames)
that will do exactly that for you.
So with a figure like this:
...running:
fig = newLegend(fig = fig, newNames = {'Australia':'Australia = Dangerous',
'New Zealand' : 'New Zealand = Peaceful'})
...will give you:
I hope this is what you were looking for. Don't hesitate to let me know if not!
import plotly.express as px
df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.pie(df, values='pop', names='country')
fig.update_traces(textposition='inside')
fig.update_layout(uniformtext_minsize=12, uniformtext_mode='hide')
def newLegend(fig, newNames):
for item in newNames:
for i, elem in enumerate(fig.data[0].labels):
if elem == item:
fig.data[0].labels[i] = newNames[item]
return(fig)
fig = newLegend(fig = fig, newNames = {'Australia':'Australia = Dangerous',
'New Zealand' : 'New Zealand = Peaceful'})
fig.show()
The challenge with your data was that genders
were of type integer
and not string
. So the custom function tried to replace an element of one type with an element of another type. I've solved this by replacing the entire array containing your labels in one go instead of manipulating it element by element.
import pandas as pd
import plotly.express as px
import numpy as np
# custom function to change labels
def newLegend(fig, newNames):
newLabels = []
for item in newNames:
for i, elem in enumerate(fig.data[0].labels):
if elem == item:
#fig.data[0].labels[i] = newNames[item]
newLabels.append(newNames[item])
fig.data[0].labels = np.array(newLabels)
return(fig)
'''
Pandas DataFrame:
'''
users_genders = pd.DataFrame({'0': {0: 1, 1: 2},
'802420': {0: 246049, 1: 106}})
users_genders = pd.DataFrame({'gender':[0,1,2],
'count_genders': [802420, 246049, 106]})
''' Pie Chart Viz '''
gender_distribution = px.pie(users_genders,
values='count_genders',
names='gender',
color_discrete_map={'0': 'blue',
'1': 'red',
'2': 'green'},
title='Gender Distribution <br>'
'between 2006-02-16 to 2014-02-20',
hole=0.35)
gender_distribution.update_traces(textposition='outside',
textinfo='percent+label',
marker=dict(line=dict(color='#000000',
width=4)),
pull=[0.05, 0, 0.03],
opacity=0.9,
# rotation=180
)
gender_distribution.update_layout(legend=dict({'traceorder': 'normal'}
# ticks='inside',
# tickvals=[0, 1, 2],
# ticktext=["0 - Female",
# "1 - Male",
# "2 - Undefined"],
# dtick=3
),
legend_title_text='User Genders')
# custom function set to work
gender_distribution=newLegend(gender_distribution, {0:"0 - Female",
1:"1 - Male",
2: "2 - Undefined"})
gender_distribution.show()