简体   繁体   English

Plotly:如何在不更改数据源的情况下更改 go.pie 图表的图例?

[英]Plotly: How to change legend for a go.pie chart without changing data source?

I am practising building a Pie Chart in Plotly Express using Python.我正在练习使用 Python 在 Plotly Express 中构建饼图。
So, this is the Pie Chart that I made;所以,这是我制作的饼图;
在此处输入图像描述

This chart was build from a file with two columns called此图表是从一个包含两列的文件构建的,称为

  1. gender with values of [0, 1, 2]值为[0, 1, 2]gender
  2. count_genders with values of [total_count_0, total_count_1, total_count_2] count_genders值为[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.如果我没记错的话,如果您想更改图例中的 label(至少在 Choropleth 地图中),您可以操纵位于colorscale栏中的ticks By manipulating them, you could rename the label about the data.通过操作它们,您可以重命名有关数据的 label。 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.我试图在update_layout中添加ticks无济于事。 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.编辑1 :如果我不清楚,我想知道是否可以修改图例中显示的值而不更改文件中的原始值。 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.编辑 2 :添加代码的导入和其他先前的详细信息,删除 Dropbox 链接。

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.可能有更优雅的方法来做到这一点,但我已经将一个自定义函数newLegend(fig, newNames)放在一起,它将为您做到这一点。

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!如果没有,请不要犹豫,让我知道!

Complete code:完整代码:

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()

Edit 1: Example with data sample from OP编辑 1:来自 OP 的数据样本示例

The challenge with your data was that genders were of type integer and not string .您的数据面临的挑战是gendersinteger而不是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.我通过一次性替换包含标签的整个数组而不是逐个元素地操作它来解决这个问题。

Plot:阴谋:

在此处输入图片说明

Complete code:完整代码:

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()
newnames = {'0': 'zero', '1': 'one', '2': 'two'}

fig.for_each_trace(lambda t: t.update(
  labels=[newnames[label] for label in t.labels]
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM