A nonexistent object was used in an Input of a Dash callback

Viewed 9533

I'm new in Plotly/Dash. I'm trying to build a sentiment analysis Dashboard.

I would like to represent the "sentiment" in a graph (realtime data: from a table) I reached my fist goal so far:

I choose: trump in my SQL.

@app.callback(
    Output("live-graph", "figure"),[Input('sentiment_term', 'value'), Input('graph-update', 'n_intervals')]
)
 #Output("wind-speed", "figure")
 #Input("wind-speed-update", "n_intervals")
 #Input("sentiment_term", "value")
 #Input("graph-update", "n_intervals")]

def gen_wind_speed(self, sentiment_term):



        conn = sqlite3.connect('twitter.db')
        c = conn.cursor()
        df = pd.read_sql("SELECT * FROM sentiment WHERE tweet LIKE '%trump%' ORDER BY unix DESC LIMIT 1000", conn)
        df.sort_values('unix', inplace=True)
        df['sentiment_smoothed'] = df['sentiment'].rolling(int(len(df)/5)).mean()
        df.dropna(inplace=True)

        X = df.unix.values[-100:]
        Y = df.sentiment_smoothed.values[-100:]

        data = plotly.graph_objs.Scatter(
                x=X,
                y=Y,
                name='Scatter',
                mode= 'lines+markers'
                )

        return {'data': [data],'layout' : go.Layout(xaxis=dict(range=[min(X),max(X)]),
                                                    yaxis=dict(range=[min(Y),max(Y)]),)}

First output

Now as second goal I would like to generate (just beside the graph) a table with the data (in this case twits) used in the graph. But when I add the table I got:

A nonexistent object was used in an Input of a Dash callback. The id of this object is recent-table-update and the property is n_intervals. The string ids in the current layout are: [live-graph, sentiment_term, graph-update, bin-slider, bin-auto, bin-size, wind-histogram, recent-tweets-table]

Which I don´t understand since I used the same Input/Output "logic" that before Second output

Complete code,, apologizes if it does´t look organized enough

import os
import pathlib
import numpy as np
import pandas as pd
import datetime as dt
import dash
import dash_core_components as dcc
import dash_html_components as html
import sqlite3
import plotly
import plotly.graph_objs as go
from dash.exceptions import PreventUpdate
from dash.dependencies import Input, Output, State
from scipy.stats import rayleigh



conn = sqlite3.connect('twitter.db', check_same_thread=False)


app_colors = {
    'pageBackground': '#272B30',
    'background': '#0C0F0A',
    'text': '#6699ff',
    'sentiment-plot':'#41EAD4',
    'volume-bar':'#6699ff',
    'someothercolor':'#80aaff',
    'papercolor':'#1E2022',
    'plotcolor':'#262626',
    'fillcolor':'#ff6666',
    'gridcolor': '#737373',
    'backgroundTableHeaders': '#001133',
    'backgroundTableRows': '#002266'
}

POS_NEG_NEUT = 0.1

MAX_DF_LENGTH = 100


GRAPH_INTERVAL = os.environ.get("GRAPH_INTERVAL", 5000)

app = dash.Dash(
    __name__,
    meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}],
)

server = app.server

app_colorsor = {"graph_bg": "#082255", "graph_line": "#007ACE"}

app.layout = html.Div(
    [
        # header
        html.Div(
            [
                html.Div(
                    [
                        html.H4("Twitter STREAMING", className="app__header__title"),
                        html.P(
                            "This app continually queries a SQL database and displays live charts of twitter sentiment analysis.",
                            className="app__header__title--grey",
                        ),
                    ],
                    className="app__header__desc",
                ),
                html.Div(
                    [
                        html.Img(
                            src=app.get_asset_url("twitter_logo.png"),
                            className="app__menu__img",
                        )
                    ],
                    className="app__header__logo",
                ),
            ],
            className="app__header",
        ),
        html.Div(
            [
                #Plot sentiment
                html.Div(
                    [
                        html.Div(
                            [html.H6("Plot sentiment", className="graph__title")]
                        ),

                        dcc.Graph(
                            id="live-graph",
                            animate=False


                         ),


                         dcc.Input(
                            id="sentiment_term",
                            value="twitter",
                            type="text"
                        ),

                        dcc.Interval(
                        id="graph-update",
                        interval=1*1000,
                        n_intervals=0


                        ),
                    ],
                    className="two-thirds column container",
                ),
                html.Div(
                    [
                        # Recent tweets table
                        html.Div(
                            [
                                html.Div(
                                    [
                                        html.H6(
                                            "Recent tweets table",
                                            className="graph__title",
                                        )
                                    ]
                                ),
                                html.Div(
                                    [
                                        dcc.Slider(
                                            id="bin-slider",
                                            min=1,
                                            max=60,
                                            step=1,
                                            value=20,
                                            updatemode="drag",
                                            marks={
                                                20: {"label": "20"},
                                                40: {"label": "40"},
                                                60: {"label": "60"},
                                            },
                                        )
                                    ],
                                    className="slider",
                                ),
                                html.Div(
                                    [
                                        dcc.Checklist(
                                            id="bin-auto",
                                            options=[
                                                {"label": "Auto", "value": "Auto"}
                                            ],
                                            value=["Auto"],
                                            inputClassName="auto__checkbox",
                                            labelClassName="auto__label",
                                        ),
                                        html.P(
                                            "# of Bins: Auto",
                                            id="bin-size",
                                            className="auto__p",
                                        ),
                                    ],
                                    className="auto__container",
                                ),
                              #it says wind because I got it from a wind direction Dash template
                                dcc.Graph(
                                    id="wind-histogram",
                                    figure=dict(
                                        layout=dict(
                                            plot_bgcolor=app_colorsor["graph_bg"],
                                            paper_bgcolor=app_colorsor["graph_bg"],
                                        )
                                    ),
                                ),
                            ],
                            className="graph__container first",
                        ),
                        # Table that I would like to add
                         html.Div(
                                    [
                                        html.H6(
                                            "Recent tweets table",
                                            className="graph__title",
                                        )
                                    ]
                                ),


                         html.Div(id="recent-tweets-table", children=[
                                      html.Thead(html.Tr( children=[], style={'color': app_colorsors['text']})),
                                      html.Tbody([html.Tr(children=[], style={'color': app_colorsors['text'],
                                                            'background-color': app_colors['backgroundTableRows'],
                                                            'border':'0.2px', 'font - size':'0.7rem'}
                                      ],

                               className='col s12 m6 l6', style={'width':'98%', 'margin-top':30, 'margin-left':15,
                                                       'margin-right':15,'max-width':500000}

                        ),
                    ],
                    className="one-third column histogram__direction",
                ),
            ],
            className="app__content",
        ),
    ],
    className="app__container",
)





dcc.Interval(
id='recent-table-update',
interval=2*1000,
n_intervals=0),




#def get_current_time():


    #now = dt.datetime.now()
    #total_time = (now.hour * 3600) + (now.minute * 60) + (now.second)
    #return total_time

def df_resample_sizes(df, maxlen=MAX_DF_LENGTH):
    df_len = len(df)
    resample_amt = 100
    vol_df = df.copy()
    vol_df['volume'] = 1

    ms_span = (df.index[-1] - df.index[0]).seconds * 1000
    rs = int(ms_span / maxlen)

    df = df.resample('{}ms'.format(int(rs))).mean()
    df.dropna(inplace=True)

    vol_df = vol_df.resample('{}ms'.format(int(rs))).sum()
    vol_df.dropna(inplace=True)

    df = df.join(vol_df['volume'])

    return df

@app.callback(
    Output("live-graph", "figure"),[Input('sentiment_term', 'value'), Input('graph-update', 'n_intervals')]
)
 #Output("wind-speed", "figure")
 #Input("wind-speed-update", "n_intervals")
 #Input("sentiment_term", "value")
 #Input("graph-update", "n_intervals")]

def gen_wind_speed(self, sentiment_term):



        conn = sqlite3.connect('twitter.db')
        c = conn.cursor()
        df = pd.read_sql("SELECT * FROM sentiment WHERE tweet LIKE '%trump%' ORDER BY unix DESC LIMIT 1000", conn)
        df.sort_values('unix', inplace=True)
        df['sentiment_smoothed'] = df['sentiment'].rolling(int(len(df)/5)).mean()
        df.dropna(inplace=True)

        X = df.unix.values[-100:]
        Y = df.sentiment_smoothed.values[-100:]

        data = plotly.graph_objs.Scatter(
                x=X,
                y=Y,
                name='Scatter',
                mode= 'lines+markers'
                )

        return {'data': [data],'layout' : go.Layout(xaxis=dict(range=[min(X),max(X)]),
                                                    yaxis=dict(range=[min(Y),max(Y)]),)}


def generate_table(df, max_rows=20):
    return html.Table(className="responsive-table",
                      children=[
                          html.Thead(
                              html.Tr(
                                  children=[
                                      html.Th(col.title()) for col in df.columns.values],
                                  style={'color': app_colorsors['text'],
                                         'background-color': app_colorsors['backgroundTableHeaders']}
                              )
                          ),
                          html.Tbody(
                              [
                                  html.Tr(
                                      children=[
                                          html.Td(data) for data in d
                                      ], style={'color': app_colorsors['text'],
                                                'background-color': quick_color(d[2]),
                                                'border':'0.2px', 'font - size':'0.7rem'}
                                  )
                                  for d in df.values.tolist()])
                      ]
                      )



@app.callback(Output("recent-tweets-table", "children"),[Input('sentiment_term','value'), Input('recent-table-update', 'n_intervals')]
 )

def update_recent_tweets(self, sentiment_term):
    genTable = html.Table()
    try:
        conn = sqlite3.connect('twitter.db')
        df = pd.read_sql("SELECT UnixTime, Tweet, Polarity FROM %s ORDER BY UnixTime DESC LIMIT 20" % (RunConfig.tableName), conn)
        if len(df)>0:
            df['Date'] = pd.to_datetime(df['UnixTime'], unit='ms')

            df = df.drop(['UnixTime'], axis=1)
            df = df[['Date', 'Tweet', 'Polarity']]
            df.Polarity = df.Polarity.round(3)

            genTable = generate_table(df, max_rows=10)

    except Exception as e:
        with open('errors.txt','a') as f:
            f.write("update_recent_tweets: " + str(e))
            f.write('\n')

    return genTable






if __name__ == "__main__":
    app.run_server(debug=True)
1 Answers

I think the problem is that you are introducing a non-existing (not yet) element in the callback as input. The element is the 'recent-table-update' which doesn't exist until you update the table. To avoid this you should introduce it in the callback as a State (it doesn't trigger the callback and the code will not break). More info: link

Here is your code:

@app.callback(
Output("recent-tweets-table", "children"),
[Input('sentiment_term','value'), 
Input('recent-table-update', 'n_intervals')]
 )

Here is my suggested code:

@app.callback(
Output("recent-tweets-table", "children"),
Input('sentiment_term','value'), 
State('recent-table-update', 'n_intervals')
 )
Related