客户端回调,用于在 Dash 中过滤数据和更新图表

Clientside callback to filter data and update graph in Dash

提问人:UgurZCifci 提问时间:8/10/2022 更新时间:8/11/2022 访问量:1885

问:

我一直在尝试从客户端回调中更新一个数字(因为我在一个页面中有 5 个数字,性能问题)。我在这里使用示例客户端回调 |Dash for Python 文档 |剧情

from dash import Dash, dcc, html, Input, Output
import pandas as pd
import json
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = Dash(__name__, external_stylesheets=external_stylesheets)

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
available_countries = df['country'].unique()

app.layout = html.Div([
    dcc.Graph(
        id='clientside-graph'
    ),
    dcc.Store(
        id='clientside-figure-store',
        data=[{
            'x': df[df['country'] == 'Canada']['year'],
            'y': df[df['country'] == 'Canada']['pop']
        }]
    ),
    'Indicator',
    dcc.Dropdown(
        {'pop' : 'Population', 'lifeExp': 'Life Expectancy', 'gdpPercap': 'GDP per Capita'},
        'pop',
        id='clientside-graph-indicator'
    ),
    'Country',
    dcc.Dropdown(available_countries, 'Canada', id='clientside-graph-country'),
    'Graph scale',
    dcc.RadioItems(
        ['linear', 'log'],
        'linear',
        id='clientside-graph-scale'
    ),
    html.Hr(),
    html.Details([
        html.Summary('Contents of figure storage'),
        dcc.Markdown(
            id='clientside-figure-json'
        )
    ])
])


@app.callback(
    Output('clientside-figure-store', 'data'),
    Input('clientside-graph-indicator', 'value'),
    Input('clientside-graph-country', 'value')
)
def update_store_data(indicator, country):
    dff = df[df['country'] == country]
    return [{
        'x': dff['year'],
        'y': dff[indicator],
        'mode': 'markers'
    }]


app.clientside_callback(
    """
    function(data, scale) {
        return {
            'data': data,
            'layout': {
                 'yaxis': {'type': scale}
             }
        }
    }
    """,
    Output('clientside-graph', 'figure'),
    Input('clientside-figure-store', 'data'),
    Input('clientside-graph-scale', 'value')
)

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

我的问题是我不想过滤数据然后存储它(在此示例中)dff = df[df['country'] == country]def update_store_data

我想按原样存储数据,然后在客户端回调中对其进行过滤,例如 ( ),然后分配 x 和 y 值。这是否可行,如果可行,我应该如何存储数据?我想将其存储为对象的JSON数组比x和y数组更合适。谢谢!dff = df[df['country'] == 'Germany']

javascript python plotly-dash 客户端

评论


答:

1赞 UgurZCifci 8/11/2022 #1

plotly论坛的帮助下,我找到了解决方案。 首先,我需要将 df 存储为序列化的 JSON (df.to_dict('records') )

然后这解决了:

clientside_callback(
    """
    function(figure_data, indicator) {
        var x_array = [];
        var y_array = [];
        var filtered_data = figure_data.filter(datum => datum["country"] === "Germany");
        filtered_data.forEach((arr)=>{x_array.push(arr.year)});
        filtered_data.forEach((arr)=>{y_array.push(arr.indicator)});
        
        var data = [{
        'x': x_array,
        'y': y_array,
    }]
        return {
            'data': data,
        }
    }
    """,
    Output('clientside-graph', 'figure'),
    [Input('clientside-figure-store', 'data'), Input('clientside-graph-indicator', 'value')]
)