Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
310 views
in Technique[技术] by (71.8m points)

pandas - Plotly Dash: Chained callbacks are working fine, but always throw ValueError. How to fix or silence?

I have a dataset that lists different jobs and what tools are need by date and location. Here is a tiny example of my df:

State,County,Job,Tool,Start,End
LA,Acadia,A,Hammer,2020-10-19,2020-11-02
LA,Acadia,A,Drill,2020-11-02,2020-12-02
LA,Acadia,B,Hammer,2020-11-28,2020-12-30
LA,Orleans,A,Hammer,2020-10-03,2020-11-02
LA,Orleans,A,Drill,2020-11-05,2020-12-02
LA,Orleans,B,Hammer,2020-12-03,2020-12-30
TX,Travis,A,Hammer,2020-10-19,2020-11-02
TX,Travis,A,Drill,2020-11-02,2020-12-02
TX,Travis,B,Hammer,2020-11-28,2020-12-30
TX,Brazoria,A,Hammer,2020-10-03,2020-11-02
TX,Brazoria,A,Drill,2020-11-05,2020-12-02
TX,Brazoria,B,Hammer,2020-12-03,2020-12-30

My dcc.Dropdowns and dcc.RadioItems are as follows:

        html.Div([
            html.Label("State:", style={'fontSize': 30, 'textAlign': 'center'}),
            dcc.Dropdown(
                id='state-dpdn',
                options=[{'label': s, 'value': s} for s in sorted(df.State.unique())],
                value='LA',
                clearable=False,
            )],
        html.Div([
            html.Label("County:", style={'fontSize': 30, 'textAlign': 'center'}),
            dcc.Dropdown(
                id='county-dpdn',
                options=[],
                value=[],
                clearable=False
            )],
        html.Div([
            html.Label("Job:", style={'fontSize': 30, 'textAlign': 'center'}),
            dcc.RadioItems(
                id='radio-buttons',
                options=[],
            ),

And here are my callbacks:

    @app.callback(
        Output('county-dpdn', 'options'),
        Output('county-dpdn', 'value'),
        Input('state-dpdn', 'value'),
    )
    def set_county_options(chosen_state):
        dff = df[df.State == chosen_state]
        counties_of_state = [{'label': c, 'value': c} for c in sorted(dff.County.unique())]
        values_selected = [x['value'] for x in counties_of_state]
        return counties_of_state, values_selected

    @app.callback(
        Output('radio-buttons', 'options'),
        Output('radio-buttons', 'value'),
        Input('county-dpdn', 'value'),
    )
    def set_job_options(chosen_county):
        dff = df[df.County == chosen_county] ###THIS IS LINE 255 W/ ERROR###
        job_of_county = [{'label': c, 'value': c} for c in dff.Job.unique()]
        values_selected = job_of_county[0]['value']
        return job_of_county, values_selected

    @app.callback(
        Output('graph1', 'children'),
        Input('radio-buttons', 'value'),
        Input('county-dpdn', 'value'),
        Input('state-dpdn', 'value')
    )
    def build_graph(job_selected, location_selected, state_selected):
        if isinstance(state_selected, str):
            df['State'].eq(state_selected)

        if isinstance(location_selected, str):
            df['County'].eq(location_selected)

        if isinstance(job_selected, str):
            df['Job'].eq(job_selected)

        dffgraph = df[df['State'].eq(state_selected) & df['County'].eq(location_selected) & df['Job'].eq(job_selected)]

        ###dffgraph manipulation and figure creation down here###

All of this works, loads the data as intended, and my graphs are great. My problem comes when trying to get this out to users without throwing errors. Errors were helpful in constructing everything but when it came time to tweak the presentation of my graphs, I silenced the errors to come back to them later using dev_tools:

if __name__ == '__main__':
    app.run_server(debug=False, port=5000, dev_tools_ui=False, dev_tools_props_check=False)

I am creating a multipage dash app which works great, but when I put this code into my main multipage app or if I remove the dev tools from the local 'app.run_server' shown above I get the following error:

File "/Users/Documents/pythonProject/app.py", line 255, in set_job_options
dff = df[df.County == chosen_county]
File "/Users/venv/lib/python3.7/site-packages/pandas/core/ops/common.py", line 65, in new_method
return method(self, other)
File "/Users/venv/lib/python3.7/site-packages/pandas/core/ops/__init__.py", line 370, in wrapper
res_values = comparison_op(lvalues, rvalues, op)
File "/Users/venv/lib/python3.7/site-packages/pandas/core/ops/array_ops.py", line 225, in comparison_op
"Lengths must match to compare", lvalues.shape, rvalues.shape
ValueError: ('Lengths must match to compare', (4781,), (64,))

The csv file used for creating my df is 4781 lines long, and 64 is the number of parishes in Louisiana, so the number make sense.

While ignoring this error has worked thus far, after weeks of trying to occasionally figure this out I would love some help with this error. Thank you!

Edit 1

For help with simply silencing the errors, it is best to show how my app is setup. I have a multipage Flask app, with my Dash app being called when the user is directed to it.

My dashboard.py file looks like:

def init_dashboard(server):
    """Create a Plotly Dash dashboard."""
    dash_app = dash.Dash(
        server=server,
        routes_pathname_prefix='/dashapp/',
        external_stylesheets=[dbc.themes.FLATLY]
    )

    # Load DataFrame
    df = create_dataframe()

    and so on....

    return dash_app.server

The init.py file in my flask app that calls my dashboard.py:

def create_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(config_class)

    .... all the normal init stuff ....

    from .plotlydash.dashboard import init_dashboard
    app = init_dashboard(app)

    return app

Prior to deployment while testing my dash app as a single entity, debug=False, dev_tools_ui=False, dev_tools_props_check=False all work well to silence the dash errors. When I put my working dash app into my flask app as shown above it still works just fine, but it throws errors which are logged and sent to my email like crazy. I've tried a few different approaches to silencing only the errors from my dash app but haven't found a solution yet.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Edit at bottom.

The problem is you're doing this:

dff = df[df.County == chosen_county]

but the == won't work with a list, and chosen_county is a list. You should do

dff = df[df.County.isin(chosen_county)]

or require that only a single value be selected and it not be a list.

Edit: To do this with a single value dropdown, I think the right way would be:

dff = df[df['County'].eq(chosen_county)]

The dropdown should not have multi=True, that was from my previous misunderstanding. Please let me know if this still is not working.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...