在 Plotly Python 上,我的小部件不起作用:当我取消选中该框时,图表不会删除

问题描述 投票:0回答:2

我尝试通过简单地根据复选框显示图表来使用小部件。

它显示了 2 个城市(格勒诺布尔和维齐尔)多年来的出生人数。

我想根据复选框显示 0、1 或 2 个城市的进化线。

一开始没问题:它显示 0 行,然后当我们选中这些框时显示 1 或 2 行。

但是如果我取消选中一个框,它不会删除一行。

我的代码中忘记了什么?

这是一个可重现的例子:

import os
import pandas as pd
import plotly.graph_objects as go
from ipywidgets import widgets

# CSV from URL
url = "https://entrepot.metropolegrenoble.fr/opendata/200040715-MET/insee/etat_civil_200040715.csv"
data_pop = pd.read_csv(url)

# Data prep
noms_col = data_pop.columns
data_pop.reset_index(inplace=True)
data_pop.drop(["code_postal"],axis=1,inplace=True)
data_pop.columns = noms_col

# Using widgets
use_Gre = widgets.Checkbox(
    description='Grenoble',
    value=False,
)

use_Viz = widgets.Checkbox(
    description='Vizille',
    value=False,
)

container_1 = widgets.HBox(children=[use_Gre, use_Viz])


g = go.FigureWidget(data=[{'type': 'scatter'}])

def validate1():
    if use_Gre.value is True:
        return True
    else:
        return False
    
def validate2():
    if use_Viz.value is True:
        return True
    else:
        return False 
    
    
def response1(change):
    if validate1():
        if use_Gre.value:
            trace01 = data_pop[data_pop['commune']=="Grenoble"].nombre_naissances
            x1=data_pop[data_pop['commune']=="Grenoble"].annee
        with g.batch_update():
            g.add_scatter(y=trace01,name="Grenoble", x= x1)
            
def response2(change):
    if validate2():
        if use_Viz.value:
            trace02 = data_pop[data_pop['commune']=="Vizille"].nombre_naissances
            x2=data_pop[data_pop['commune']=="Vizille"].annee
        with g.batch_update():
            g.add_scatter(y=trace02,name="Vizille", x= x2)
            
            
use_Gre.observe(response1, names="value")
use_Viz.observe(response2, names="value")

widgets.VBox([container_1, g])
python plotly plotly-python ipywidgets
2个回答
1
投票

我可以建议使用 plotly.express 吗?它将显着减少您的代码,并且已经具有显示/隐藏图例中的图的功能:

import pandas as pd
import plotly.express as px

# CSV from URL
url = "https://entrepot.metropolegrenoble.fr/opendata/200040715-MET/insee/etat_civil_200040715.csv"
data_pop = pd.read_csv(url)

# Data prep
noms_col = data_pop.columns
data_pop.reset_index(inplace=True)
data_pop.drop(["code_postal"],axis=1,inplace=True)
data_pop.columns = noms_col

# keeping only the two cities of interest
data_pop = data_pop[data_pop['commune'].isin(['Grenoble', 'Vizille'])]

fig = px.line(x=data_pop['annee'], 
              y=data_pop['nombre_naissances'],
              color=data_pop['commune'])

# the option legendonly can be set to hide plot by default
for scat in fig.data:
    if scat.legendgroup == "Vizille":
        scat.visible = "legendonly"

fig.show()

输出:

关于您的代码,问题是每次您选中该框时您的响应函数都会重新绘制数据,但是当您取消选中该框时您不会删除它(您应该在 else 块中执行此操作)

编辑:更正了有关

legendonly

的代码部分

0
投票

您可以首先绘制轨迹并使用

visible
属性,而不是绘制一个空图形并向其添加轨迹。

正如@Tranbi 所建议的那样,使用图例切换可以解决问题,您不一定需要复选框小部件。

不过,假设您更喜欢隐藏图例并仅使用小部件(即计划添加城市和/或更多小部件),并坚持使用 plotly.graph_objects,您可以重构代码如下:

# Data prep
noms_col = data_pop.columns
data_pop.reset_index(inplace=True)
data_pop.drop(["code_postal"],axis=1,inplace=True)
data_pop.columns = noms_col

cities = ['Grenoble', 'Vizille']

# Named lists 
checkboxes = dict()
traces = dict()

for city in cities:
    # Widget
    checkboxes[city] = widgets.Checkbox(description=city, value=False)

    # Trace
    x = data_pop[data_pop['commune']==city].annee
    y = data_pop[data_pop['commune']==city].nombre_naissances
    traces[city] = go.Scatter(name=city, x=x, y=y, visible=False)

container_1 = widgets.HBox(children=list(checkboxes.values()))
fig = go.FigureWidget(data=list(traces.values()), layout=dict(showlegend=False))

def response(change):
    city = change.owner.description
    fig.update_traces(selector=dict(name=city), visible=checkboxes[city].value)

for checkbox in list(checkboxes.values()):
    checkbox.observe(response, names='value')

widgets.VBox([container_1, fig])
© www.soinside.com 2019 - 2024. All rights reserved.