Black Lives Matter. Please consider donating to Black Girls Code today.

Connecting Backend Paging with a Graph - Multiple Graphs

Hello!

I’ve followed the Dash user guide on Connecting Backend Paging with a Graph (https://dash.plot.ly/datatable/callbacks), but I want to place multiple graphs with different x and y axes and not just the same x axis as is featured in the guide. I attempted to do this but instead got this error. Info under Activity is confidential, so I replaced it with a bold line for this question only.

Note: all the two square brackets facing each other has turned into checkboxes for some unknown reason. Please assume they are just two square brackets.

Invalid argument id passed into Div with ID “[object Object]”.
Expected string.
Was supplied type array.
Value provided:
[
{
“props”: {
“id”: “Activity”,
“figure”: {
“data”: [
{
“x”: [
“Y”,
“N”,
“N”,
“N”,
null,
“N”,
“Y”,
null,
null,
null,
null,
null,
“Y”,
“Y”,
null,
“N”,
“N”,
“Y”,
null,
“Y”,
“Y”,
“Y”,
“Y”,
“N”,
null,
null,
null,
null,
null,
null,
null
],
“y”: [
confidential, but it listed out all the stuff under Activity
],
“type”: “bar”,
“marker”: {
“color”: “#0074D9
}
}
],
“layout”: {
“xaxis”: {
“automargin”: true
},
“yaxis”: {
“automargin”: true
},
“height”: 400,
“margin”: {
“t”: 40,
“l”: 10,
“r”: 10
}
}
}
},
“type”: “Graph”,
“namespace”: “dash_core_components”
}
]

Listed below is my code. The section where I attempted to add a 2nd graph will be represented by a different blockquote.

import dash
from dash.dependencies import Input, Output, State
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd

app = dash.Dash(name)
df = pd.read_csv(‘data/dashboard_data.csv’)

PAGE_SIZE = 10

app.layout = html.Div(
className=“row”,
children=[
html.Div(
dash_table.DataTable(
id=‘table-sorting-filtering’,
columns=[
{‘name’: i, ‘id’: i, ‘deletable’: True} for i in sorted(df.columns)
],
page_current= 0,
page_size= 31,
page_action=‘custom’,
filter_action=‘custom’,
filter_query=’’,
sort_action=‘custom’,
sort_mode=‘multi’,
sort_by=,
),
style={‘height’: 750, ‘overflowY’: ‘scroll’},
className=‘six columns’
),
html.Div(
id=‘table-paging-with-graph-container’,
className=“five columns”
),
dcc.Interval(id=‘interval_component’, interval = 5000, n_intervals=0)
]
)

operators = [['ge ', ‘>=’],
['le ', ‘<=’],
['lt ', ‘<’],
['gt ', ‘>’],
['ne ', ‘!=’],
['eq ', ‘=’],
['contains '],
['datestartswith ']]

def split_filter_part(filter_part):
for operator_type in operators:
for operator in operator_type:
if operator in filter_part:
name_part, value_part = filter_part.split(operator, 1)
name = name_part[name_part.find(’{’) + 1: name_part.rfind(’}’)]
value_part = value_part.strip()
v0 = value_part[0]
if (v0 == value_part[-1] and v0 in ("’", ‘"’, ‘`’)):
value = value_part[1: -1].replace(’\’ + v0, v0)
else:
try:
value = float(value_part)
except ValueError:
value = value_part
# word operators need spaces after them in the filter string,
# but we don’t want these later
return name, operator_type[0].strip(), value
return [None] * 3

@app.callback(
Output(‘table-sorting-filtering’, ‘data’),
[Input(‘table-sorting-filtering’, “page_current”),
Input(‘table-sorting-filtering’, “page_size”),
Input(‘table-sorting-filtering’, ‘sort_by’),
Input(‘table-sorting-filtering’, ‘filter_query’),
Input(‘interval_component’, ‘n_intervals’)])

def update_table(page_current, page_size, sort_by, filter, n_intervals):
filtering_expressions = filter.split(’ && ')
dff = df
for filter_part in filtering_expressions:
col_name, operator, filter_value = split_filter_part(filter_part)
if operator in (‘eq’, ‘ne’, ‘lt’, ‘le’, ‘gt’, ‘ge’):
# these operators match pandas series operator method names
dff = dff.loc[getattr(dff[col_name], operator)(filter_value)]
elif operator == ‘contains’:
dff = dff.loc[dff[col_name].str.contains(filter_value)]
elif operator == ‘datestartswith’:
# this is a simplification of the front-end filtering logic,
# only works with complete fields in standard format
dff = dff.loc[dff[col_name].str.startswith(filter_value)]
if len(sort_by):
dff = dff.sort_values(
[col[‘column_id’] for col in sort_by],
ascending=[
col[‘direction’] == ‘asc’
for col in sort_by
],
inplace=False
)
return dff.iloc[
page_current*page_size:(page_current+ 1)*page_size
].to_dict(‘records’)

def update_rows(n_intervals, n_clicks):
data = pd.read_csv(‘data/dashboard_data.csv’)
dict = data.to_dict(‘records’)

return dict

@app.callback(
Output(‘table-paging-with-graph-container’, “children”),
[Input(‘table-sorting-filtering’, “data”)])

def update_graph(rows):
dff = pd.DataFrame(rows)
return html.Div(
[
dcc.Graph(
id=graph1,
figure={
“data”: [
{
“x”: dff[“Activity”],
“y”: dff[graph1] if graph1 in dff else ,
“type”: “bar”,
“marker”: {“color”: “#0074D9”},
}
],
“layout”: {
“xaxis”: {“automargin”: True},
“yaxis”: {“automargin”: True},
“height”: 400,
“margin”: {“t”: 40, “l”: 10, “r”: 10},
},
},
)
for graph1 in [“Time Spent (hrs)”]
],
[
dcc.Graph(
id=graph2,
figure={
“data”: [
{
“x”: dff[“Touch Point?”],
“y”: dff[graph2] if graph2 in dff else ,
“type”: “bar”,
“marker”: {“color”: “#0074D9”},
}
],
“layout”: {
“xaxis”: {“automargin”: True},
“yaxis”: {“automargin”: True},
“height”: 400,
“margin”: {“t”: 40, “l”: 10, “r”: 10},
},
},
)
for graph2 in [“Activity”]
]
)

The other code past this is just a callback for intervals and the app.run_server function.

Activity is a column with things like ‘Clean Rooms’
Touch Points? has Y and N and empty space
Time Spent (hrs) is numbers

If anyone can figure out why this is creating an error and how to make multiple graphs with diff axes, then your help would be much appreciated! :slight_smile: