python Plotly条形图-使用下拉菜单选择一列,然后让条形图按列排序?

dxpyg8gm  于 2023-05-05  发布在  Python
关注(0)|答案(1)|浏览(157)

我的目标是:

我想有一个单一的水平条形图plotly python与一个单一的下拉菜单。下拉菜单选项是给定数据框的所有列名。我希望条形图根据下拉列表中选择的任何列进行排序。这样的事情可能吗?

我目前拥有的:

我有一个dataframe,看起来像这样:

我的代码看起来像这样:

def gen_bar(df, title, sub, col='Podium'):
    """
    Displays an interactive plotly graph using the given column and dataframe.
    
    df: dataframe containing relevant data
    col: data to be displayed along x-axis
    title: title (and subtitle) for given visualization
    """
    # Top 10 men and women
    comb = df.sort_values(col, ascending=False)[:20]
    
    # Define colors
    color_discrete_map = {"M": "#10baee", "F": "#ff007e"}
    
    # Define plot
    fig=go.Figure()
    for r in comb['Name'].unique():
        dfp = comb[comb['Name'] == r]
        g = dfp['Gender'].values[0]
        fig.add_traces(
            go.Bar(x=dfp[col], 
                   y=dfp['Name'],
                   customdata=[col],
                   name='', 
                   marker_color=color_discrete_map[g], 
                   orientation='h',
                   hovertemplate="<b>%{y}</b><br>%{customdata}: %{x}"
                   ))
        
    
# Define buttons for dropdown
    col_opts = list(df.columns[4:])
    buttons_opts = []
    for i, opt in enumerate(col_opts):
        args = [False] * len(col_opts)
        args[i] = True
        buttons_opts.append(
            dict(
                method='restyle',
                label=opt,
                args=[{
                    'visible': args, #this is the key line!
                    'title': opt,
                    'showlegend': False
                }]
            )
        )
        
    # Styling
    title = f"{title}<br><sup>{sub}"
    fig.update_layout(
        updatemenus = [go.layout.Updatemenu(
            active=col_opts.index(col),
            buttons=buttons_opts,
            x=1.12,
            xanchor='right',
            y=1.1,
            yanchor='top'
            )],
        yaxis={
            'autorange': "reversed",
            'showline': True,
            'linecolor': 'black',
            'title': None
        },
        title=dict(text=title, font=dict(size=30)),
        showlegend=False,
        width=1000,
        height=600,
        plot_bgcolor='#f0f0f0',
        paper_bgcolor='#f0f0f0',
        xaxis_title=None,
        margin=dict(l=85, r=85, t=95, b=45)
    )
    
    fig.show(config=config)
    
title = "Top 20 Climbers in IFSC"
sub = f"Based on total number of given value"
gen_bar(all_boulder_podiums, title, sub, 'Podium')

生成如下图:

问题:

当下拉菜单工作时,图表不能正确更新。我对plotly的了解还不足以真正弄清楚我错在哪里,但是例如,如果我从下拉列表中选择“Gold”列,购物车会更新为:

如何实现所需的更改?我想这不会太难,但我在这里,几个小时后试图弄清楚这一点。任何帮助是赞赏!

emeijp43

emeijp431#

我认为原因是单个图形是按名称创建的。因此,创建的图表中的数据框按目标列的降序排序,并设置为仅显示第一个数据框。此外,对于性别颜色编码,我需要一个颜色列表,因此我通过引用数据框中的字典创建了一个颜色列表。“活动”按钮确定要显示为初始显示的图形的编号,并设置为要显示的第一个图形(默认值为0)。

import plotly.graph_objects as go

def gen_bar(df, title, sub):
    """
    Displays an interactive plotly graph using the given column and dataframe.
    
    df: dataframe containing relevant data
    col: data to be displayed along x-axis
    title: title (and subtitle) for given visualization
    """
    # Top 10 men and women
    #comb = df.sort_values(col, ascending=False)[:20]
    comb = df[:20]
    
    # Define colors
    color_discrete_map = {"M": "#10baee", "F": "#ff007e"}
    
    # Define plot
    fig=go.Figure()
    for k,r in enumerate(df.columns[4:]):
        #dfp = comb[comb['Name'] == r]
        dfp = comb.sort_values(r, ascending=False)
        g = dfp['Gender'].values
        print(g)
        colors = [color_discrete_map[x] for x in g]
        fig.add_traces(
            go.Bar(x=dfp[r], 
                   y=dfp['Name'],
                   customdata=dfp[r].values,
                   name='', 
                   marker_color=colors,#color_discrete_map[g], 
                   orientation='h',
                   hovertemplate="<b>%{y}</b><br>%{customdata}: %{x}",
                   visible=True if k == 0 else False
                   ))
        
    
# Define buttons for dropdown
    col_opts = list(df.columns[4:])
    buttons_opts = []
    for i, opt in enumerate(col_opts):
        args = [False] * len(col_opts)
        args[i] = True
        buttons_opts.append(
            dict(
                method='restyle',
                label=opt,
                args=[{
                    'visible': args, #this is the key line!
                    'title': opt,
                    'showlegend': False
                }]
            )
        )
        
    # Styling
    title = f"{title}<br><sup>{sub}"
    fig.update_layout(
        updatemenus = [go.layout.Updatemenu(
            active=0,#col_opts.index(col),
            buttons=buttons_opts,
            x=1.12,
            xanchor='right',
            y=1.1,
            yanchor='top'
            )],
        yaxis={
            'autorange': "reversed",
            'showline': True,
            'linecolor': 'black',
            'title': None
        },
        title=dict(text=title, font=dict(size=30)),
        showlegend=False,
        width=1000,
        height=600,
        plot_bgcolor='#f0f0f0',
        paper_bgcolor='#f0f0f0',
        xaxis_title=None,
        margin=dict(l=85, r=85, t=95, b=45)
    )
    # print(fig.data)
    fig.show()#config=config
    
title = "Top 20 Climbers in IFSC"
sub = f"Based on total number of given value"
gen_bar(all_boulder_podiums, title, sub)

相关问题