如何正确使用Plotly中过滤数据的按钮

2024-05-18 22:13:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个看起来像这样的数据框,其中“dni”是每行的唯一id。我想在每个dni的日期列中使用plotly作为堆叠条形图

^{tb1}$

我当前使用的代码如下所示:

fig = go.Figure()
buttons = []

for i,dni in enumerate(sorted(df_merged.dni.unique())):
  df = df_merged[df_merged['dni']==dni]
  for column in df.columns[3:-1]:
      fig.add_trace(go.Bar(
                        name = column,
                        x = pd.to_datetime(df.date.astype('str')),
                        y = df[column], 
                        visible = (i==0)
                      ))
  args = [False] * df_merged.dni.nunique()
  args[i] = True
    
  button = dict(label = dni,
                method = "update",
                args=[{"visible": args}])
      
  buttons.append(button)
        
fig.update_layout(
    updatemenus=[
        dict(
        type="dropdown",
        direction="down",
        buttons = buttons)
    ],
    barmode = "stack",)
fig.show()

这确实给了我一个带有过滤器的绘图,但它显示的数据总是不正确的。我正在努力理解我错在哪里。它显示的唯一正确数据是第一个dni,当我实际按下按钮时,该数据也会更改。 Rendered plotly graph

谢谢

编辑: 这是实际数据:

           id      date  bills  goalTrans  incomes  payments  savings
0  12345678901  2020-12    1.0        2.0      1.0       0.0      0.0
1  23456789012  2021-02    6.0        0.0      2.0       0.0      0.0
2  34567890123  2020-12    4.0        0.0      2.0       0.0      0.0
3  45678901234  2020-12    9.0        1.0      1.0       0.0      0.0
4  56789012345  2021-01    3.0        0.0      2.0       1.0      0.0

{'bills': {0: 1.0, 1: 6.0, 2: 4.0, 3: 9.0, 4: 3.0},
 'date': {0: '2020-12',
  1: '2021-02',
  2: '2020-12',
  3: '2020-12',
  4: '2021-01'},
 'id': {0: '12345678901',
  1: '23456789012',
  2: '34567890123',
  3: '45678901234',
  4: '56789012345'},
 'goalTrans': {0: 2.0, 1: 0.0, 2: 0.0, 3: 1.0, 4: 0.0},
 'incomes': {0: 1.0, 1: 2.0, 2: 2.0, 3: 1.0, 4: 2.0},
 'payments': {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 1.0},
 'savings': {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}}

Tags: 数据inidgodffordatefig
1条回答
网友
1楼 · 发布于 2024-05-18 22:13:31

切中要害:

这可能是一个相当困难的问题,但是您已经错误地指定了visible属性,因为您的四个子集有三个跟踪,所以您需要每个arg有十二个规范,而不是像您在设置中那样有四个规范

解决方案:

答案末尾的完整代码段将生成下图,其中启动了第一个对接选项:

子集1:

# 00820054194
   bills     date          dni  goalTrans  incomes  payments  savings
0    1.0  2020-12  00820054194        2.0      1.0       0.0      0.0

图1:

enter image description here

如果你把Subset 1Plot 1相比较,你会发现我们到目前为止都很好。我将让您验证所有子集,但这里是最后一个四舍五入的子集:

子集4:

# 04902852446
   bills     date          dni  goalTrans  incomes  payments  savings
3    9.0  2020-12  04902852446        1.0      1.0       0.0      0.0
4    3.0  2021-01  04902852446        0.0      2.0       1.0      0.0

图4:

enter image description here

据我所知,这正是你想要的

详细信息:

在最后一次迭代中:

for i,dni in enumerate(sorted(df_merged.dni.unique())):

args中的{}如下所示:

[False, False, False, False, True]

这并没有涵盖设置中的所有选项。你看,{}中的{}当{}要查找并可能更改{}中的{}属性时,Wwat会这样做,在你的例子中,它是一个元组,包含十二个元素,其中第一个元素如下所示:

(Bar({
     'name': 'goalTrans',
     'visible': True,
     'x': array([datetime.datetime(2020, 12, 1, 0, 0)], dtype=object),
     'y': array([2.])
 }),

为什么是12岁?因为数据帧的四个子集有三个go.Bar()跟踪。因此,为了触发更新菜单的正确跟踪和正确选择选项(是,按钮)的可见性,您不需要:

[False, False, False, False, True]

但这是:

[[True, True,True,False, False, False, False, False, False, False, False, False],
 [False, False, False, True, True, True, False, False, False, False, False, False],
 [False, False, False, False, False, False, True, True, True, False, False, False],
 [False, False, False, False, False, False, False, False, False, True, True, True]]

或者更确切地说,外部列表的每个元素都以迭代方式出现在:

for i, dni in enumerate(sorted(df_merged.dni.unique()[:])):

。。。像这样:

button =  dict(label=dni,
               method = 'restyle',
                args = ['visible',visibility[i]]
              )

。。。其中,作为示例,visibility[2]如下所示:

[False, False, False, False, False, False, False, False, False, True, True, True]

这就是下面完整代码中有点神秘的部分所要处理的:

frames = len(df_merged.dni.unique())
bars = len(df.columns[3:-1])
scenarios = [list(s) for s in [e==1 for e in np.eye(frames)]]
visibility = [list(np.repeat(e, bars)) for e in scenarios]
<>你可以肯定地考虑把一些线移出循环,因为它们被重复了不必要的次数,但是我发现让这些步骤彼此接近更可读。还有问题吗?别客气,尽管问吧!事情是这样的:

完整代码:

import pandas as pd
import numpy as np
import plotly.graph_objects as go
df_merged = pd.DataFrame({'bills': {0: 1.0, 1: 6.0, 2: 4.0, 3: 9.0, 4: 3.0},
                     'date': {0: '2020-12',
                      1: '2021-02',
                      2: '2020-12',
                      3: '2020-12',
                      4: '2021-01'},
                     'dni': {0: '00820054194',
                      1: '01717705014',
                      2: '02252584041',
                      3: '04902852446',
                      4: '04902852446'},
                     'goalTrans': {0: 2.0, 1: 0.0, 2: 0.0, 3: 1.0, 4: 0.0},
                     'incomes': {0: 1.0, 1: 2.0, 2: 2.0, 3: 1.0, 4: 2.0},
                     'payments': {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 1.0},
                     'savings': {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}})

fig = go.Figure()
buttons = []

frames = len(df_merged.dni.unique())
for i, dni in enumerate(sorted(df_merged.dni.unique()[:])):
    df = df_merged[df_merged['dni']==dni]
    print(dni)
    print(df)
    
    args_data = []
    bars = len(df.columns[3:-1])
    for c, column in enumerate(df.columns[3:-1]):
        fig.add_trace(go.Bar(
                        name = column,
                        x = pd.to_datetime(df.date.astype('str')),
                        y = df[column], 
                        visible=False
                      ))
    
    frames = len(df_merged.dni.unique())
    bars = len(df.columns[3:-1])
    scenarios = [list(s) for s in [e==1 for e in np.eye(frames)]]
    visibility = [list(np.repeat(e, bars)) for e in scenarios]   
        
    button =  dict(label=dni,
                   method = 'restyle',
                    args = ['visible',visibility[i]]
                  )
    
    buttons.append(button)
       
fig.update_layout(
    updatemenus=[
        dict(
        type="dropdown",
        direction="down",
        buttons = buttons)
    ],
    barmode = "stack",)
f = fig.full_figure_for_development(warn=False)

fig.show()

相关问题 更多 >

    热门问题