首页 > 编程问答 >Dash Python:通过 @callback 链接选项卡

Dash Python:通过 @callback 链接选项卡

时间:2024-08-07 04:23:03浏览次数:10  
标签:python callback plotly plotly-dash

这个问题是下面链接的问题的扩展:

Dash Python:布局函数中的@Callback未被调用

我有一个简单的数据框:

import pandas as pd
df = pd.DataFrame({'Class1': [1, 2, 3, 4, 5],
                   'Class2': [6, 7, 8, 9, 10]}
)  

我创建了一个数据提取函数,该函数根据列的位置。

data_extraction.py

def dataExtraction(arg1):

    df = pd.DataFrame({'Class1': [1, 2, 3, 4, 5],
                             'Class2': [6, 7, 8, 9, 10]})  ## <-- or Import df from somewhere
    df = df[[f'Class{arg1}']]

    return df   

tab_page.py

import layout as lay
import data_extraction as de
import dash_bootstrap_components as dbc
from dash import html, Dash
import dash

app = Dash()

dash.register_page(__name__, 
                   path='/tabs') 

def get_layout(position):
        df = de.dataExtraction(position)
        layout = lay.update_page(position, df)
        return layout


tab1_content = dbc.Card(
    dbc.CardBody(
        [
                get_layout(1)
        ]
    ),
    className="mt-1",
)

tab2_content = dbc.Card(
    dbc.CardBody(
        [
                get_layout(2)
        ]
    ),
    className="mt-2",
)

layout = html.Div(children = [
    dbc.Tabs(
    [
        dbc.Tab(tab1_content, label="1",activeLabelClassName="text-success"),
        dbc.Tab(tab2_content, label="2",activeLabelClassName="text-success"),
   ]
)])


app.layout = [layout]

lay.create_callback(1)
lay.create_callback(2)  

if __name__ == '__main__':
    app.run(debug=True)

layout.py

from dash import dcc, html, Input, Output, callback
from dash import Dash, dash_table, State
import dash_daq as daq
import pandas as pd

def update_page_test(arg1, arg2):
    layout = html.Div(children=[html.H1(f'Class {arg1}'),

    daq.NumericInput(
        id=f'numericinput{arg1}',
        min=0,
        max=100,
        value=0, )

        , html.Br(),

        dash_table.DataTable(
            id=f'tableTest{arg1}',
            data=arg2.to_dict('records'),
            columns=[{"name": i, "id": i} for i in arg2.columns]),

        dcc.Store(id=f'{arg1}mystore', data=[],storage_type='memory'),
])

return layout

def create_callback(i):

    @callback(
    Output(f'tableTest{i}', 'data'),
    Input(f'numericinput{i}', 'value'),
    State(f'tableTest{i}', 'data'),
    State(f'{i}mystore', 'data'),
    )
    def updateTableTest(x,data, Orig):


        data = pd.DataFrame(data)
        Orig = pd.DataFrame(Orig)

        if x > 0:

            print(f'Callback for class {i} works')

            data.iloc[:,1:] = Orig.iloc[:,1:]*x

            return data.to_dict('records')
        return Orig.to_dict('records')

    return updateTableTest

我想构造一个包含 3 个选项卡的页面的选项卡页。像这样的事情:

...

total_content = dbc.Card(
    dbc.CardBody(
        [
            html.Div([
                html.Div(id='table-placeholder', children=[])
            ], className='row')
        ]
    ),
    className="mt-3",
)


layout = html.Div(children = [

    dbc.Tabs(
    [
        dbc.Tab(tab1_content, label="1",activeLabelClassName="text-success"),
        dbc.Tab(tab2_content, label="2",activeLabelClassName="text-success"),
        dbc.Tab(total_content, label="total",activeLabelClassName="text-success"),

    ]
),

])

问题: 我如何能够更新layout.py部分,以便总计选项卡使用其他选项卡总和中的数据进行更新,并且当数字输入框调整时总计也会更新更新?

例如,如果选项卡 1:[1,2,3] 选项卡 2:[4,5,6] -> 总计:[5,7,9]。如果选项卡 1 中的数字输入框设置为 2,则结果将为选项卡 1: [2,4,6] 选项卡 2: [4,5,6] -> 总计:[6,9,12]

我正在考虑使用另一个回调选项来更新每个选项卡中的存储数据,然后将其输出到总选项卡中,但我不确定这将如何工作。我已经尝试过这个,但我被卡住了:

def update_store(i):
    @callback(
        Output(f'{i}mystore', 'data'),
        Input(f'tableTest{i}', 'data'),
    )
    def Update(data):
        print(f'Callback update store {i} works')
        print(data)
        return data
    return Update

def output_total(i):
    @callback(
        Output('table-placeholder', 'children'),
        State(f'{i}mystore', 'data'),
    )
    def create_total_table(data):
        print(f'Callback of create Total {i} works')
        return data
    return create_total_table

好的,我们可以通过一些调整来实现这个功能。以下是如何使用回调函数和 dcc.Store 组件链接选项卡以计算总和的示例:

1. 修改 layout.py

from dash import dcc, html, Input, Output, callback
from dash import Dash, dash_table, State
import dash_daq as daq
import pandas as pd

def update_page_test(arg1, arg2):
    layout = html.Div(children=[
        html.H1(f'Class {arg1}'),

        daq.NumericInput(
            id=f'numericinput{arg1}',
            min=0,
            max=100,
            value=0,
        ),

        html.Br(),

        dash_table.DataTable(
            id=f'tableTest{arg1}',
            data=arg2.to_dict('records'),
            columns=[{"name": i, "id": i} for i in arg2.columns]
        ),

        dcc.Store(id=f'{arg1}mystore', data=arg2.to_dict('records'), storage_type='memory'),
    ])
    return layout

def create_callback(i):
    @callback(
        [Output(f'tableTest{i}', 'data'),
         Output(f'{i}mystore', 'data')],
        Input(f'numericinput{i}', 'value'),
        State(f'{i}mystore', 'data')
    )
    def updateTableTest(x, data):
        data = pd.DataFrame(data)
        if x > 0:
            print(f'Callback for class {i} works')
            data.iloc[:, 1:] = data.iloc[:, 1:] * x
        return data.to_dict('records'), data.to_dict('records')
    return updateTableTest

def create_total_callback():
    @callback(
        Output('table-placeholder', 'children'),
        [Input('1mystore', 'data'), Input('2mystore', 'data')]
    )
    def update_total_table(data1, data2):
        df1 = pd.DataFrame(data1)
        df2 = pd.DataFrame(data2)
        df_total = df1.add(df2)

        total_table = dash_table.DataTable(
            id='tableTotal',
            data=df_total.to_dict('records'),
            columns=[{"name": i, "id": i} for i in df_total.columns]
        )
        return total_table
    return update_total_callback

2. 修改 tab_page.py

import layout as lay
import data_extraction as de
import dash_bootstrap_components as dbc
from dash import html, Dash
import dash

app = Dash(__name__)

dash.register_page(__name__,
                   path='/tabs')

def get_layout(position):
    df = de.dataExtraction(position)
    layout = lay.update_page_test(position, df)
    return layout

tab1_content = dbc.Card(
    dbc.CardBody(
        [
            get_layout(1)
        ]
    ),
    className="mt-1",
)

tab2_content = dbc.Card(
    dbc.CardBody(
        [
            get_layout(2)
        ]
    ),
    className="mt-2",
)

total_content = dbc.Card(
    dbc.CardBody(
        [
            html.Div([
                html.Div(id='table-placeholder', children=[])
            ], className='row')
        ]
    ),
    className="mt-3",
)

layout = html.Div(children=[
    dbc.Tabs(
        [
            dbc.Tab(tab1_content, label="1", activeLabelClassName="text-success"),
            dbc.Tab(tab2_content, label="2", activeLabelClassName="text-success"),
            dbc.Tab(total_content, label="total", activeLabelClassName="text-success"),
        ]
    ),
])

app.layout = layout

lay.create_callback(1)
lay.create_callback(2)
lay.create_total_callback()

if __name__ == '__main__':
    app.run_server(debug=True)

解释:

  • update_page_test 函数:
    • 我们不再需要 update_store 函数,因为我们在 create_callback 中直接更新 dcc.Store
  • create_callback 函数:
    • 现在,它同时输出到 tableTest{i} f'{i}mystore' ,以保持数据同步。
  • create_total_callback 函数:
    • 这个新函数创建了一个回调函数,用于监听两个 dcc.Store 组件的变化。
    • 当任何一个选项卡的数据发生变化时,它会读取两个 dcc.Store 的数据,计算总和,并更新 “Total” 选项卡中的表格。

现在,的应用程序应该能够在每个选项卡中显示数据,并在 “Total” 选项卡中显示它们的总和,并且当更改数字输入框时,总和会相应更新。

标签:python,callback,plotly,plotly-dash
From: 78840847

相关文章

  • 如何在 Python 中使用 Langchain 返回已使用的上下文以进行回答
    我已经构建了一个像这样的RAG系统:defformat_docs(docs):return"\n\n".join(doc.page_contentfordocindocs)response_schemas=[ResponseSchema(name="price",description="Price",type="float"),ResponseSchema(......
  • 如何从 python socket.sendmsg 获取套接字 Tx 时间戳
    在阅读此处、此处和此处时,我发现在Linux系统上,您可以通过设置套接字选项来请求接收和传输的数据包的时间戳。我目前可以使用SO_TIMESTAMPNS和SO_TIMESTAMPING来通过recvmsg获取Rx时间戳。使用sendmsg我不知道......
  • Python 类型注释中“|”两边是否“强制”使用空格?
    “Union运算符”|没有出现在PEP8的其他建议中的“始终被空格包围的运算符”列表中因此,应该可以将其样式设置为类似于算术运算符,并删除圆括号、方括号内的空格,或者如果该运算符比表达式中的其他运算符具有更高的优先级。在我看来,删除空格可以提高表达式......
  • ArcPro (3.2+) Python 脚本工具中从 .atbx Toolbox 相对导入本地模块
    我设置了一个库和关联的ArcGISToolbox,以便:/root├──Toolbox.atbx├──mylib│└──my_function.py├──my_tools│└──my_gp_script.py我将代码存储库的开发克隆保存在公司共享服务器上的一个位置,并在GitHub上托管一份副本。当我进行更新时,我会......
  • Python vs. R:揭秘机器学习领域的双璧
    一、引言1.1背景介绍随着大数据和人工智能技术的飞速发展,机器学习已经成为了一个热门领域。在机器学习领域,Python和R是两种广泛使用的编程语言。Python因其简洁易读的语法和强大的库支持,成为了最受欢迎的编程语言之一。而R则以其强大的统计分析和数据可视化能力,在统计学......
  • Windows10 安装编译后的 pysqlcipher3-1.2.1 基于 Python 3.8.10
    Windows10安装编译后的pysqlcipher3-1.2.1基于Python3.8.10本文主要是将直接安装编译后的文件,不一定的成功,但是可以尝试使用,若无法直接安装,请参考编译过程,自行编译安装,编译过程见这里安装pysqlcipher3这里用32位举例因为64位安装完全相同,只需要把对应的位数换成64......
  • 【Python】Python基础语法知识点汇集
    Python是一种高级的、解释型的编程语言,以其清晰的语法和代码可读性而闻名。本篇文章将汇集Python编程的基础语法知识点,为初学者提供一个全面的学习指南。......
  • 启动Python 的内置服务器访问本地图片
    要使用Python的内置服务器访问本地图片并正确地显示在浏览器中,你需要将图片文件放在内置服务器的根目录或其子目录中。以下是详细步骤:1.将图片文件复制到服务器根目录:例如,将zheng.jpeg文件复制到一个特定的目录中(例如,你的项目目录)。假设你将图片文件复制到C:\Users\panda......
  • 17:Python数据类型练习题
    #1获取c1,c2相同的元素列表c1=[11,22,33]c2=[22,33,44]foriinc1:ifiinc2:print(i)#2获取c1中有,c2没有的元素列表foriinc1:ifinotinc2:print(i)#3获取c2中有,c1没有的元素列表foriinc2:ifinotinc1:print(i)#4获......
  • (Jmeter新玩法)Python 调 Jmeter执行参数化jmx脚本
    #Python调Jmeter执行参数化jmx脚本importosfromos.pathimportjoinimporttimeimportrefromstringimportTemplatejmeter_Home=r"F:\softtotal\xxx\bin\jmeter.bat"#jmx文件路径currpath=os.path.dirname(os.path.realpath(__file__))#要运行的jmx脚......