How to read and plot the rows in a csv file in way that it reads each row in each second?

Hello,
I want to read a csv file and plot the data in a way that every second a row of the csv file be read, and added to the plot until it reaches the last row. I looked into live-updates and many other posts but still could not figure it out.
here is the code I have. In my csv file, I have 3 columns of X, Y and Z and I want to have a 3d-scatter plot.

from dash import Dash, html, dcc, Output, Input, State, MATCH, ALL, callback
import pandas as pd
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
import json
import time

path = 'C:/Users/...'  # the path for the csv file

app = Dash(__name__)

app.layout = html.Div([
                dcc.Dropdown(id='dropdown1',
                             options=['file1'],   # name of the csv file
                             clearable=True,
                             value=[]
                             ),

                dcc.Graph(id='graph1'),
                dcc.Store(id='table1'),
                dcc.Interval(id='interval-component',
                             interval=1 * 1000,  # in milliseconds
                             n_intervals=0)
])


# callback to store and share the df between callbacks
@callback(
    Output('table1', 'data'),
    Input('dropdown1', 'value'),
    prevent_initial_call=True
)
def store_df(chosen_file):
    if chosen_file is None:
        return dash.no_update
    else:
        df = pd.read_csv(path + chosen_file + '.csv')
        df_json = df.to_json(date_format='iso', orient='split')
    return df_json

@callback(
    Output('graph1', 'figure'),
    Input('table1', 'data'),
    Input('interval-component', 'n_intervals'),
    prevent_initial_call=True
)
def callback_stats(js_df, n_clicks):
    df = pd.read_json(js_df, orient='split')

    fig = go.Figure()
    fig.add_trace(
        go.Scatter3d(x=df['X'], y=df['Y'], z=df['Z'], mode='markers'))

    return fig

if __name__ == "__main__":
    app.run(debug=True, port=8051)

Hey @Peyman,

You are just missing the loc for the n_intervals to get passed to the df, something like:

df = df.iloc[n_clicks-1]

Thanks for your reply. Do you mean add it here:

def callback_stats(js_df, n_clicks):
     df = pd.read_json(js_df, orient='split')
     df = df.iloc[n_clicks-1]

right now, every second I get this error: ValueError: Invalid file path or buffer object type: <class ‘NoneType’>

Try this:

from dash import Dash, html, dcc, Output, Input, State, MATCH, ALL, callback
import pandas as pd
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
import json
import time
import dash

path = 'C:/Users/...'  # the path for the csv file

app = Dash(__name__)

app.layout = html.Div([
                dcc.Dropdown(id='dropdown1',
                             options=['file1'],   # name of the csv file
                             clearable=True,
                             value=[]
                             ),

                dcc.Graph(id='graph1'),
                dcc.Store(id='table1'),
                dcc.Interval(id='interval-component',
                             interval=1 * 1000,  # in milliseconds
                             n_intervals=0)
])


# callback to store and share the df between callbacks
@callback(
    Output('table1', 'data'),
    Output('interval-component', 'n_intervals'),
    Input('dropdown1', 'value'),
    prevent_initial_call=True
)
def store_df(chosen_file):
    if chosen_file is None:
        return dash.no_update, dash.no_update
    else:
        df = pd.read_csv(path + chosen_file + '.csv')
        df_json = df.to_dict('records')
    return df_json, 0

@callback(
    Output('graph1', 'figure'),
    Input('interval-component', 'n_intervals'),
    State('table1', 'data'),
    prevent_initial_call=True
)
def callback_stats(n_clicks, js_df):
    if js_df:
        df = pd.DataFrame(js_df)
        df = df.iloc[n_clicks-1]

        fig = go.Figure()
        fig.add_trace(
            go.Scatter3d(x=df['X'], y=df['Y'], z=df['Z'], mode='markers'))

        return fig
    return dash.no_update

if __name__ == "__main__":
    app.run(debug=True, port=8051)

Thank you, I get this error:
ValueError:
Invalid value of type ‘numpy.int64’ received for the ‘x’ property of scatter3d
Received value: 39
The ‘x’ property is an array that may be specified as a tuple,
list, numpy array, or pandas Series

Ok, try this, I converted the data into a list. :slight_smile:

from dash import Dash, html, dcc, Output, Input, State, MATCH, ALL, callback
import pandas as pd
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
import json
import time
import dash

path = 'C:/Users/...'  # the path for the csv file

app = Dash(__name__)

app.layout = html.Div([
                dcc.Dropdown(id='dropdown1',
                             options=['file1'],   # name of the csv file
                             clearable=True,
                             value=[]
                             ),

                dcc.Graph(id='graph1'),
                dcc.Store(id='table1'),
                dcc.Interval(id='interval-component',
                             interval=1 * 1000,  # in milliseconds
                             n_intervals=0)
])


# callback to store and share the df between callbacks
@callback(
    Output('table1', 'data'),
    Output('interval-component', 'n_intervals'),
    Input('dropdown1', 'value'),
    prevent_initial_call=True
)
def store_df(chosen_file):
    if chosen_file is None:
        return dash.no_update, dash.no_update
    else:
        df = pd.read_csv(path + chosen_file + '.csv')
        df_json = df.to_dict('records')
    return df_json, 0

@callback(
    Output('graph1', 'figure'),
    Input('interval-component', 'n_intervals'),
    State('table1', 'data'),
    prevent_initial_call=True
)
def callback_stats(n_clicks, js_df):
    if js_df:
        df = pd.DataFrame(js_df)
        df = df.iloc[n_clicks-1]

        fig = go.Figure()
        fig.add_trace(
            go.Scatter3d(x=[df['X']], y=[df['Y']], z=[df['Z']], mode='markers'))

        return fig
    return dash.no_update

if __name__ == "__main__":
    app.run(debug=True, port=8051)

Thanks @jinnyzor. this one works well. thank you. maybe that was my incomplete post. I wondered how we can keep the previous points in the plot?

We just need to get the figure.

This is set to refresh the graph upon different file selection.

from dash import Dash, html, dcc, Output, Input, State, MATCH, ALL, callback
import pandas as pd
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
import json
import time
import dash

path = 'C:/Users/...'  # the path for the csv file

app = Dash(__name__)

app.layout = html.Div([
                dcc.Dropdown(id='dropdown1',
                             options=['file1'],   # name of the csv file
                             clearable=True,
                             value=[]
                             ),

                dcc.Graph(id='graph1'),
                dcc.Store(id='table1'),
                dcc.Interval(id='interval-component',
                             interval=1 * 1000,  # in milliseconds
                             n_intervals=0)
])


# callback to store and share the df between callbacks
@callback(
    Output('table1', 'data'),
    Output('interval-component', 'n_intervals'),
    Input('dropdown1', 'value'),
    prevent_initial_call=True
)
def store_df(chosen_file):
    if chosen_file is None:
        return dash.no_update, dash.no_update
    else:
        df = pd.read_csv(path + chosen_file + '.csv')
        df_json = df.to_dict('records')
    return df_json, 0

@callback(
    Output('graph1', 'figure'),
    Input('interval-component', 'n_intervals'),
    State('table1', 'data'),
    State('graph1', 'figure'),
    prevent_initial_call=True
)
def callback_stats(n_clicks, js_df, fig):
    if js_df:
        df = pd.DataFrame(js_df)
        if n_clicks-1 > len(df):
             return dash.no_update
        if n_clicks-1 == 0:
            fig = go.Figure()
        df = df.iloc[n_clicks-1]

        fig.add_trace(
            go.Scatter3d(x=[df['X']], y=[df['Y']], z=[df['Z']], mode='markers'))

        return fig
    return dash.no_update

if __name__ == "__main__":
    app.run(debug=True, port=8051)

Dear @jinnyzor, I know I asked a lot for my post. I still don’t understand what you have done in the code. I am trying to run the code without an error, and then think of what is going on in the code. I get this error now: AttributeError: ‘dict’ object has no attribute ‘add_trace’

Alright, I think I got it now. :slight_smile:

from dash import Dash, html, dcc, Output, Input, State, MATCH, ALL, callback
import pandas as pd
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
import json
import time
import dash

path = 'C:/Users/....'  # the path for the csv file

app = Dash(__name__)

app.layout = html.Div([
                dcc.Dropdown(id='dropdown1',
                             options=['file1'],   # name of the csv file
                             clearable=True,
                             value=[]
                             ),

                dcc.Graph(id='graph1'),
                dcc.Store(id='table1'),
                dcc.Interval(id='interval-component',
                             interval=1 * 1000,  # in milliseconds
                             n_intervals=0)
])


# callback to store and share the df between callbacks
@callback(
    Output('table1', 'data'),
    Output('interval-component', 'n_intervals'),
    Input('dropdown1', 'value'),
    prevent_initial_call=True
)
def store_df(chosen_file):
    if chosen_file is None:
        return dash.no_update, dash.no_update
    else:
        df = pd.read_csv(path + chosen_file + '.csv')
        df_json = df.to_dict('records')
    return df_json, 0

@callback(
    Output('graph1', 'figure'),
    Input('interval-component', 'n_intervals'),
    State('table1', 'data'),
    State('graph1', 'figure'),
    prevent_initial_call=True
)
def callback_stats(n_clicks, js_df, fig):
    if js_df:
        df = pd.DataFrame(js_df)
        if n_clicks-1 >= len(df):
             return dash.no_update
        if n_clicks-1 <= 0:
            fig = go.Figure()
        else:
            fig = go.Figure(**fig)
        df = df.iloc[n_clicks-1]

        fig.add_trace(
            go.Scatter3d(x=[df['X']], y=[df['Y']], z=[df['Z']], mode='markers'))

        return fig
    return dash.no_update

if __name__ == "__main__":
    app.run(debug=True, port=8051)

@jinnyzor Thanks you are awesome.

1 Like