Виджеты панели не обновляют график

Я пытаюсь использовать виджеты панели внутри класса, чтобы изменить сюжет. В приведенном ниже примере график выводится один раз, но когда я выбираю другую переменную в виджете, график не обновляется.

import pandas as pd
import param

import holoviews as hv
hv.extension('bokeh')

import panel as pn
pn.extension()

df = pd.DataFrame({'index':[1,2,3,4,5],
                   'signal1':[1,2,3,4,5],
                   'signal2':[5,4,3,2,1]}).set_index('index')

class Plot(param.Parameterized):
    def __init__(self, df):
        self.multi_select = pn.widgets.MultiSelect(name='Vars', value=['signal1'],
                                                   options=['signal1', 'signal2'])
        self.df = df
        self.watcher = self.multi_select.param.watch(self.dashboard, 'value')
        super().__init__()

    def dashboard(self, *events, **kwargs):
        self.plt = hv.Curve(self.df, [self.df.index.name, self.multi_select.value[0]])
        return self.plt

a = Plot(df)
pn.Row(a.multi_select,a.dashboard)

Однако, если вместо виджетов панели я использую param, он работает как положено.

class Plot2(param.Parameterized):
    multi_select = param.ListSelector(default=['signal1'],
                                      objects=['signal1', 'signal2'])

    df = df

    def dashboard(self, **kwargs):
        self.plt = hv.Curve(self.df, [self.df.index.name, self.multi_select[0]])
        return self.plt

b = Plot2()
pn.Row(b.param,b.dashboard)

Я что-то не так делаю или это вообще невозможно? Спасибо

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
1 840
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сначала я немного изменил ваш код. Основные изменения: я добавил

  • предложение try-except в Plot.dashboard() с операторами печати для события и переменной self.multi_select
  • использовал внешний боке-сервер с view = pn.Row(a.multi_select,a.dashboard) и view.app(), чтобы получить отпечатки из пункта try-кроме.

Полный сюжет():

class Plot(param.Parameterized):

    def __init__(self, df, **params):
        super(Plot, self).__init__(**params)
        self.multi_select = pn.widgets.MultiSelect(name='Vars', value=['signal1'],
                                                   options=['signal1', 'signal2'])
        self.df = df
        self.watcher = self.multi_select.param.watch(self.dashboard, 'value')


    def dashboard(self, *events, **kwargs):
        try: 
            event = events[0] # get first event in events
            select = events[0].obj # obj is our multi_select

            # see, what event looks like, and if select and self.multi_select are the same
            print(event, '\n', select, '\n', self.multi_select)

        except IndexError: pass

        self.plt = hv.Curve(self.df, [self.df.index.name, self.multi_select.value[0]])
        return self.plt

a = Plot(df)
view = pn.Row(a.multi_select,a.dashboard)
view.app()

Итак, ваш код работает, как и следовало ожидать, но изменения не отображаются.

Второй: Отделение графика Curve от множественного выбора и игра вокруг показывает, что кривая изменяется только в том случае, если метод view зависит от измененного параметра (здесь имя столбца, используемого для графика):

class Curve_(param.Parameterized):
    col = param.String()

    def __init__(self, df, col, **params):
        super(Curve_, self).__init__(**params)
        self.df = df
        self.col = col

    @param.depends('col', watch=True)
    def view(self): 
        return hv.Curve(self.df, [self.df.index.name, self.col])

t=Curve_(df, 'signal1')
pn.Column(t.view)

Объединив классы Plot и Curve_ и используя параметр dashboard_trigger для обновления панели инструментов, теперь все работает, как и ожидалось.

class Plot(param.Parameterized):
    dashboard_trigger = param.Number(1)

    def __init__(self, df, **params):
        super(Plot, self).__init__(**params)
        self.multi_select = pn.widgets.MultiSelect(name='Vars', value=['signal1'],
                                                   options=['signal1', 'signal2'])
        self.curve = Curve_(df, self.multi_select.value[0])
        self.watcher = self.multi_select.param.watch(self.set_column, 'value')

    def set_column(self, *events):
        self.curve.col = events[0].obj.value[0]
        self.dashboard_trigger = self.dashboard_trigger + 1

    @param.depends('dashboard_trigger', watch=True)
    def dashboard(self, *events, **kwargs):
        return self.curve.view

a = Plot(df)
pn.Row(a.multi_select,a.dashboard)

Другие вопросы по теме