简体   繁体   English

在回调之间共享数据帧

[英]Sharing dataframe between callbacks

I am trying to share dataframe between callbacks but i keep getting this error.我正在尝试在回调之间共享数据帧,但我不断收到此错误。 I want to use dcc.store to the data.我想对数据使用 dcc.store。 Then I will have one callback filtering the data while the other callback plotting the graph.然后我将有一个回调过滤数据,而另一个回调绘制图形。

"Callback error updating main_data.data" “回调错误更新 main_data.data”

My code run fine if I include everything in one callback, but it won't work once I split it.如果我将所有内容都包含在一个回调中,我的代码运行良好,但是一旦我拆分它,它将无法工作。

import dash
import pathlib
import numpy as np
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
from flask import Flask

df =pd.read_csv("salesfunnela.csv") 
mgr_options = df["Manager"].unique()
mgr_options = np.insert(mgr_options, 0 , 'All Managers')

server = Flask(__name__)
app = dash.Dash(server=server)

app.layout = html.Div([
    dcc.Store(id='main_data'),
    html.Div(
        [
            html.P("Div1", className="control_label"),
            dcc.Dropdown(
                id="Manager",
                options=[{
                    'label': i,
                    'value': i
                } for i in mgr_options],
                value='All Managers'),
        ],
        style={'width': '25%',
               'display': 'inline-block'}),
    dcc.Graph(id='funnel-graph'), 
        html.Div(
        [
            html.P("Div2", className="abc"),

        ],
        style={'width': '25%',
               'display': 'inline-block'}),
])


@app.callback(
    dash.dependencies.Output('main_data', 'data'),
    [dash.dependencies.Input('Manager', 'value')])
def update_data(Manager):
    if Manager == "All Managers":
        df_plot = df.copy()
    else:
        df_plot = df[df['Manager'] == Manager]

    return df_plot

@app.callback(
    dash.dependencies.Output('funnel-graph', 'figure'),
    [dash.dependencies.Input('main_data', 'data')])
def update_graph(main_data):
    pv = pd.pivot_table(
    df_plot,
    index=['Name'],
    columns=["Status"],
    values=['Quantity'],
    aggfunc=sum,
    fill_value=0)


    
    traces = [go.Bar(x=pv.index, y=pv[('Quantity', t[1])], name=t[1]) for t in pv]

    
    return {
        'data': traces,
        'layout':
        go.Layout(
            title='Customer Order Status for {}'.format(Manager),
            barmode='stack')
    }


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

Some time has passed but I hope this might help.一段时间过去了,但我希望这可能会有所帮助。

What is basically discussed in previous answer is to change def update_graph(main_data) to def update_graph(df_plot) , or alternatively, change df_plot in the function to main_data if you like.什么在前面的回答基本上是讨论是改变def update_graph(main_data)def update_graph(df_plot)或者改变df_plot在功能main_data如果你喜欢。 this will most likely not solve your problem though .不过,这很可能无法解决您的问题 Since the problem is that the function update_data cannot store the data in the first place.由于问题在于函数update_data无法首先存储数据。 The idea to store the filtered data somewhere is probably a good idea, instead of sending it through chained callbacks.将过滤后的数据存储在某处的想法可能是一个好主意,而不是通过链式回调发送它。

In the section for sharing data between callbacks in the docs/getting started guide ( https://dash.plotly.com/sharing-data-between-callbacks ), it says that you have to store the data as either JSON or base64 encoded binary data .在文档/入门指南 ( https://dash.plotly.com/sharing-data-between-callbacks ) 的回调之间共享数据部分中,它说您必须将数据存储为 JSON 或 base64 编码二进制数据 A Pandas DataFrame is not binary data in an ASCII string format (base64), if you want to encode a DataFrame in base64 you should probably convert it to a string first and then encode that into base64 (eg https://docs.python.org/3/library/base64.html ). Pandas DataFrame 不是 ASCII 字符串格式 (base64) 的二进制数据,如果您想以 base64 编码 DataFrame,您可能应该先将其转换为字符串,然后将其编码为 base64(例如https://docs.python。 org/3/library/base64.html )。 So in your example code, to use JSON, you would have to change the return statement to因此,在您的示例代码中,要使用 JSON,您必须将 return 语句更改为

return df_plot.to_json(date_format='iso', orient='split')

in the update_data function.update_data函数中。

Then in update_graph you would now need to convert the JSON back into Pandas DataFrame.然后在update_graph您现在需要将 JSON 转换回 Pandas DataFrame。 The first few lines of that function would then look like this instead该函数的前几行看起来像这样

def update_graph(main_data):
    df_plot = pd.read_json(main_data, orient='split')
    pv = pd.pivot_table(
        df_plot,
        index=['Name'],
        columns=["Status"],
        values=['Quantity'],
        aggfunc=sum,
        fill_value=0)

I hope this helps, and that it's not too late.我希望这会有所帮助,而且现在还为时不晚。

You probably want to read more about Chained callbacks...你可能想阅读更多关于链式回调的信息......
Docs - https://dash.plotly.com/basic-callbacks文档 - https://dash.plotly.com/basic-callbacks
Scroll down to the section: Dash App With Chained Callbacks向下滚动到以下部分: Dash App With Chained Callbacks

In the docs-example, you'll notice that the data is not really passed between two callbacks.在文档示例中,您会注意到数据并未真正在两个回调之间传递。
Rather they work like event listeners, listening to updates in the DOM.相反,它们像事件侦听器一样工作,侦听 DOM 中的更新。

In your case, there's nothing called "main-data" in the layout, which the second callback is trying to listen to.在您的情况下,布局中没有任何称为“主数据”的内容,第二个回调正在尝试侦听。
Try to play around with 'funnel-graph' or 'Div2' or setup another element whose updates can be tracked by these callbacks.尝试使用 'funnel-graph' 或 'Div2' 或设置另一个可以通过这些回调跟踪其更新的元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM