Hello, I am trying to add a px.timeline to my dashboard with callback function in order to update the timeline based on filtering. However, I am not really familiar with the callbacks with px graphs and it does not show on my dashboard even though I think I correctly assign the callback functions. Here is part of my code (I did not put irrelevant part):
#----------App layout----------------------------------------------------------------------
app = dash.Dash(external_stylesheets=[dbc.themes.CYBORG])
app.layout = dbc.Container([
html.Div([
html.H2('Timelines', className="second-section-title"),
dcc.Graph(id='timeline')
]),
])
#----------Callback for timeline graphs------------------------------------------------------------
@app.callback(
[Output('timeline', 'figure')],
[Input('input_subject','value')]
)
def update_timeline_graph(input_subject):
# when there is no subject chosen
if input_subject is None:
dff = timeline_data
else:
dff = timeline_data[timeline_data == input_subject]
timeline_graph = px.timeline(dff,
x_start="Start",
x_end="End",
y="Subject",
color='Type')
timeline_graph.update_xaxes(tickformat="%H:%M:%S",
tickformatstops=[dict(dtickrange=[1800000, 10800000], value="%H:%M")])
timeline_graph.update_yaxes(categoryorder="category ascending")
timeline_graph.update_layout({'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)'})
return (timeline_graph)
I don’t not really know how it is wrong since I followed the examples I found online
HI @yunyihuang
don’t worry about updating_axes and yaxes or making the graph pretty for now. Let’s focus on getting the graph to show up.
In the callback you declare an Input that refers to a component with the ID - ‘input_subject’. Where is that component? I can’t see it in the layout.
Also, can you provide example data so we can reproduce this code/problem on our computers. Here are some Plotly datasets.
Ah, sorry, did not notice that when removing some irrelevant code. The main problem for me is that when I put the dcc.Graph(id=“timeline”) in HTML, it only shows a regular empty grid graph instead of a plotly express graph.
Here is the part where I set up the input:
#code
dcc.Dropdown(id='input_subject',
#className="dropdown-menu",
options=[{'label': x, 'value': x} for x in df["Subject"].unique()],
style={"width": "100%"},
placeholder = 'All Data',
searchable=False,
clearable=True)
It is a dropdown menu.
Here is the data I have: timeline_data.
I can show you the full code if it is needed, it’s only about 180 lines.
hi @yunyihuang
the main problem was that you put Output and Input in []
. They don’t need to go inside a list.
Some subjects had the same start and end time. I’m sure there is a way to plot your data by playing around with Pandas and datetime type. However, to show you a demo of how this plot works, I changed F1501 to have different start and end days in the data.
from dash import Dash, dcc, html, Input , Output
import plotly.express as px
import dash_bootstrap_components as dbc
import pandas as pd
df = pd.read_csv("timeline_data.xlsx - Sheet1.csv")
df["Start"] = pd.to_datetime(df["Start"])
df["Start"] = df["Start"].dt.strftime("%Y-%m-%d")
df["End"] = pd.to_datetime(df["End"])
df["End"] = df["End"].dt.strftime("%Y-%m-%d")
for x in df["End"][:5]:
print(x)
print(type(x))
# exit()
# ----------App layout----------------------------------------------------------------------
app = Dash(external_stylesheets=[dbc.themes.CYBORG])
app.layout = dbc.Container([
html.Div([
html.H2('Timelines', className="second-section-title"),
dcc.Dropdown(id='input_subject',
#className="dropdown-menu",
options=[{'label': x, 'value': x} for x in df["Subject"].unique()],
style={"width": "100%"},
placeholder = 'All Data',
searchable=False,
value="F1501",
clearable=True),
dcc.Graph(id='timeline')
]),
])
# ----------Callback for timeline graphs------------------------------------------------------------
@app.callback(
Output('timeline', 'figure'),
Input('input_subject', 'value')
)
def update_timeline_graph(input_subject):
print(input_subject)
if input_subject is None:
dff = df.copy()
else:
dff = df[df["Subject"]==input_subject]
print(input_subject)
print(dff)
timeline_graph = px.timeline(dff,
x_start="Start",
x_end="End",
y="Type",
color='Subject')
# timeline_graph.update_xaxes(tickformat="%H:%M:%S",
#
# tickformatstops=[dict(dtickrange=[1800000, 10800000], value="%H:%M")])
#
# timeline_graph.update_yaxes(categoryorder="category ascending")
#
# timeline_graph.update_layout({'plot_bgcolor': 'rgba(0, 0, 0, 0)',
#
# 'paper_bgcolor': 'rgba(0, 0, 0, 0)'})
return timeline_graph
if __name__ == '__main__':
app.run_server(debug=True)
1 Like
Hey Adam, thank you so much. And you are right, the brackets were the reason and I can now see my graph!
The data only has the time when the action happened (only start time), I don’t have the end time so basically what I did was to add a 20-seconds interval in order to actually show something on the timeline. There are overlaps, but it’s fine for me at this point. Thanks again and I will watch more of your tutorials on YouTube 
1 Like