首页 > 解决方案 > Plotly - 将多个子图与下拉菜单按钮相结合

问题描述

我有各个公司的月度销售信息(金额、利润),并希望在一个交互式 Plotly 图表中显示所有这些信息 - 即对于每个独特的公司,应该有一个条形图显示每月的销售额以及显示每月利润的折线图,这两个图表将共享时间的 x 轴,但有单独的 y 轴(参见下面的示例)。

对于使用子图的单个公司来说,这很简单,但我希望能够使用下拉菜单在公司之间切换。我已经能够让soething正常工作,但是遇到了各种我无法解决的错误。

重现数据的代码:

import pandas as pd
import numpy as np
import itertools
from datetime import datetime

np.random.seed(2021)

company_list = ['Company_A', 'Company_B', 'Company_C', 'Company_D', 'Company_E']
datelist = pd.date_range(start="2020-01-01", end='2021-01-01', freq='MS').to_list()

df = pd.DataFrame(list(itertools.product(company_list, datelist)))
df.columns = ['Company', 'Date']

df['Amount'] = np.random.choice(range(0,10000), df.shape[0])
df['Profit'] = np.random.choice(range(0,10000), df.shape[0])


df.head()

在此处输入图像描述

我有一个函数,它接受一个数据框(假设与上面刚刚创建的格式相同)并创建一个 Plotly 图表,其中包含每个公司的两个图(金额和利润),并且有一个下拉菜单可以从公司更改到公司。

制作多个绘图和下拉菜单的功能:

from plotly import graph_objs as go
from plotly.subplots import make_subplots

def make_multi_plot(df):
    
    fig = make_subplots(rows=2, cols=1,
                    shared_xaxes=True,
                    vertical_spacing=0.02)

    for customer in list(df.Company.unique()):
        
        trace1 = go.Bar(
            x=df.loc[df.Company.isin([customer])].Date, 
            y=df.loc[df.Company.isin([customer])].Amount, 
            name = "Amount - " + str(customer))

        trace2 = go.Scatter(
                x=df.loc[df.Company.isin([customer])].Date,
                y=df.loc[df.Company.isin([customer])].Profit,
                name = "Profit - " + str(customer)
            )

        fig.append_trace(trace1,1,1)
        fig.append_trace(trace2,2,1)


    def create_layout_button(customer):
        return dict(label = customer,
                    method = 'restyle',
                    args = [{'visible': [cust == customer for cust in list(df.Company.unique())],
                             'title': customer,
                             'showlegend': True}])

    fig.update_layout(
        updatemenus=[go.layout.Updatemenu(
            active = 0,
            buttons = [create_layout_button(customer) for customer in list(df.Company.unique())]
            )
        ])
    
    fig.show()

乍一看,这似乎正在做我想要的。但是,我遇到了 2 个我无法解决的问题:

  1. 首次调用该函数时,它会在两个图上绘制所有公司的数据,而不仅仅是第一家公司(这是我想要的)。一旦您从下拉菜单中选择了一家公司,这确实会自行解决,尽管这会将我们介绍给我们的下一个问题......首次调用 make_multi_plot 函数时的输出

  2. 当您从下拉菜单中选择公司时,它实际上并没有正确更新绘图,而是使用错误的公司数据来制作绘图。如果您查看这两个图的图例,您会发现它实际上是在绘制集合中不同公司的数据。我不知道为什么会发生这种情况,也无法找到任何真正的模式来混淆各种图与按钮。当您从下拉列表中选择一家公司时,它不会使用正确的数据更新图表

感谢任何和所有的帮助!

标签: pythonpandasplotly

解决方案


推荐阅读