How to view plotly dash interactive table in nbviewer or github? - python

I have code that creates an interactive table using dash - I do this in Juypterlab and the code works just fine for me to view and interact with the table in Juypterlab, but when I upload the ipynb notebook to github and look at the notebook in nbviewer the table no longer loads and I get an error that says Requests to the server have been blocked by an extension.
If I try firefox browser I get an error that says
An error occurred during a connection to 126.2.3.3:8054. SSL received a record that exceeded the maximum permissible length.
Error code: SSL_ERROR_RX_RECORD_TOO_LONG
Trying with browers google chrom and brave also give similar errors saying Requests to the server have been blocked by an extension.
I'm having trouble finding the setting I'm missing to make the table viewable - is there a dash setting I'm missing? Do I need to make the 8054 port accessible somehow or is it an extension in my web browser causing the problem?
The code I have that makes the dash table looks like this
plotly.offline.init_notebook_mode()
import dash
from dash.dependencies import Input, Output
import plotly.express as px
from jupyter_dash import JupyterDash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
app = JupyterDash(__name__)
X_interactive = data
app.layout = html.Div([
dash_table.DataTable(
id='datatable-interactivity',
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True} for i in X_interactive.columns
],
data=X_interactive.to_dict('records'),
editable=True,
filter_action="native",
sort_action="native",
sort_mode="multi",
column_selectable="single",
row_selectable="multi",
row_deletable=True,
selected_columns=[],
selected_rows=[],
page_action="native",
page_current= 0,
page_size= 10,
),
html.Div(id='datatable-interactivity-container')
])
#app.callback(
Output('datatable-interactivity', 'style_data_conditional'),
Input('datatable-interactivity', 'selected_columns')
)
def update_styles(selected_columns):
return [{
'if': { 'column_id': i },
'background_color': '#D2F3FF'
} for i in selected_columns]
#app.callback(
Output('datatable-interactivity-container', "children"),
Input('datatable-interactivity', "derived_virtual_data"),
Input('datatable-interactivity', "derived_virtual_selected_rows"))
def update_graphs(rows, derived_virtual_selected_rows):
if derived_virtual_selected_rows is None:
derived_virtual_selected_rows = []
dff = X_interactive if rows is None else pd.DataFrame(rows)
colors = ['#7FDBFF' if i in derived_virtual_selected_rows else '#0074D9'
for i in range(len(dff))]
return [
dcc.Graph(
id=column,
figure={
"data": [
{
"x": dff["Gene"],
"y": dff[column],
"type": "bar",
"marker": {"color": colors},
}
],
"layout": {
"xaxis": {"automargin": True},
"yaxis": {
"automargin": True,
"title": {"text": column}
},
"height": 250,
"margin": {"t": 10, "l": 10, "r": 10},
},
},
)
# check if column exists - user may have deleted it
# If `column.deletable=False`, then you don't
# need to do this check.
for column in ["col1", "col2", "col3"] if column in dff
]
app.run_server(mode='inline', port=8054)

Related

Turn ON/OFF AutoUpdate base on boolean switch (Dash, Python)

How do I please enable/disable auto-update (n_intervals) based on a boolean switch?
When the switch is turned off so that auto-update is not performed. And when it is on, so that the table is updated every 6 seconds?
Below I am posting the code that works for me with autoupdate (n_intervals).
import pandas as pd
import dash
from dash import html, Input, Output, callback, dash_table, dcc
import database
database = database.database()
dash.register_page(__name__)
layout = html.Div(
[
html.Div(id="table-container", children=[]),
dcc.Interval(id='interval-component', interval=6000, n_intervals=0),
]
)
#callback(Output('table-container', 'children'), [Input('interval-component', 'n_intervals')])
def update_table(n_intervals):
sql = pd.read_sql_query("SELECT * FROM PY_LOGGING ORDER BY LOG_TIME DESC FETCH FIRST 500 ROWS ONLY", database.connection())
df = pd.DataFrame(sql)
table = dash_table.DataTable(
id='table',
data = df.to_dict('records'),
columns = [{"name": i, "id": i} for i in df.columns],
fill_width=True,
page_size=20,
filter_action='native',
sort_action='native',
sort_mode='multi',
sort_as_null=['', 'No'],
style_table = {
"overflow": "hidden",
},
style_header = {
"text-transform": "uppercase",
"backgroundColor": "#333",
"color": "#FFFFFF",
"padding": "15px",
},
style_cell_conditional=[
{
'if': {'column_id': 'text_message'},
'textAlign': 'left'
}
],
style_data={
'whiteSpace': 'normal',
'height': 'auto',
'border-top': "1px solid #333",
'border-bottom': "1px solid #333",
'border-left': "0px solid #333",
'border-right': "0px solid #333",
},
style_data_conditional = [
{"if": {"column_id": "text_message"}, "width": "50%"},
{"if": {"column_id": "log_time"}, "width": "10%"},
{"if": {"column_id": "name_process"}, "width": "10%"},
{"if": {"column_id": "name_machine"}, "width": "10%"},
],
style_cell = {
# "padding": "15px",
"font-size": "0.8em",
}
)
return table
Thank you very much for your help.
John

Dash datatable calculations using active cell callback trigger to update the source datatable

I have a data table whose goal is to perform excel like computations and display results in a column within the same table.
Using the active cell trigger I am able to perform the computation in pandas by getting the table data dict but I am however having trouble with updating the datatable in question. I have been getting the nonetype error when the callback attempts to update the datatable. Below is my datatable and callback code any help will be appreciated.
dash_table.DataTable(
editable=True,
row_deletable=True,
sort_action="native",
sort_mode="single",
# filter_action="native",
column_selectable="single",
row_selectable="multi",
page_action="none", .
style_table={
"margin": "auto%",
"width": "80%",
"overflowY": "auto",
},
id="request_table",
data=df.to_dict("records"),
columns=[
{
"name": "Item_ID",
"id": "Item_ID",
"deletable": False,
"renamable": False,
"editable": True,
},
{
"name": "Price",
"id": "Price",
"deletable": True,
"renamable": True,
"editable": True,
"type": "numeric",
},
{
"name": "Quantity",
"id": "Quantity",
"deletable": False,
"renamable": False,
"editable": True,
"type": "numeric",
},
{
"name": "Line Total",
"id": "Line_Total",
"deletable": False,
"renamable": False,
"editable": False,
"type": "numeric",
},
]
# active_cell=initial_active_cell,
),
#app.callback(
[Output("request_table", "data")],
[Output("request_table", "columns")],
Input("request_table", "active_cell"),
State("request_table", "data"),
)
def getActiveCell(active_cell, rows):
if active_cell:
datacalc = datax.from_dict(rows)
datacalc["Line_Total"] = datacalc["Price"] * datacalc["Quantity"]
data = datacalc.to_dict("records")
# data = list(itertools.chain(datacalc))
return data
I modified an example from the dash document. The callback rewrite the data using the defined rule and it can be used as the output. Just need to be cautious that the row values would become string so data type needs change before calculation.
from dash import Dash, dash_table, html
from dash.dependencies import Input, Output
app = Dash(__name__)
app.layout = html.Div([
dash_table.DataTable(
id='editing-table-data',
columns=[{
'name': 'Column {}'.format(i),
'id': 'column-{}'.format(i)
} for i in range(1, 5)],
data=[
{'column-{}'.format(i): i for i in range(1, 5)}
for j in range(5)
],
editable=True
)
])
#app.callback(Output('editing-table-data', 'data'),
Input('editing-table-data', 'data'),
prevent_initial_call=True)
def display_output(rows):
for row in rows:
# update the data using a newly defined rule
if all([cell != '' for cell in row.values()]):
row['column-2'] = int(row['column-1']) * 10 + 1
return rows
if __name__ == '__main__':
app.run_server(debug=True)

unable to add google form in plotly

Below is my code, but the code not works,
first 5 options in dropdown returns a graph and
option 6 needs to display a google form
without the 6th option the code is working fine, but the 6th option for displaying gform is throwing errror in dash
help me solve this
app.layout=html.Div(children=[dcc.Dropdown(
id='FirstDropdown',
options=[
{'label':"graph1",'value':'v1'},
{'label':"graph2",'value':'v2'},
{'label':"graph3,'value':'v3'},
{'label':"graph4",'value':'v4'},
{'label':"graph 5",'value':'v5'},
{'label':"g-form",'value':'v6'}
],
placeholder="Please choose an option",
value='v1'
),
html.Div(dcc.Graph(id='graph'))
])
#app.callback(
[Output('graph','figure')],
[Input(component_id='FirstDropdown',component_property='value')]
)
def select_graph(value):
if value=='v1':
return fig11
elif value=='v2':
return fig21
elif value=='v3':
return fig31
elif value=='v4':
return fig411
elif value=='v5':
return fig_all
elif value == 'v6':
google_form_iframe = html.Iframe(
width='640px',
height='947px',
src="https://docs.google.com/forms/d/e/1FAIpQLSfkIgHkKlD5Jl4ewfWpA8y9D65UbhdrvZ0k7qXOBI7uFN1aNA/vi ewform?embedded=true"
)
return google_form_iframe
fundamentally dcc.Figure() and html.IFrame() are separate dash components. Hence if you what to display a figure of Iframe based on dropdown use a div container. From callback return child component that fits into this container
to make full working example, have used COVID vaccination data to generate 5 figures that can be selected from drop down.
if google form is selected then return that
import pandas as pd
import plotly.express as px
from jupyter_dash import JupyterDash
import dash
from dash import dcc, html
from dash.dependencies import Input, Output, State
import json
df = pd.read_csv(
"https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.csv"
)
df["date"] = pd.to_datetime(df["date"])
df = df.sort_values(["date", "iso_code"])
figs = {
f"v{n+1}": px.bar(
df.loc[(df["date"].dt.day_of_week == 6) & df["iso_code"].isin(["DEU", "FRA"])],
x="date",
y=c,
color="iso_code",
)
for n, c in zip(range(5), df.select_dtypes("number").columns)
}
# Build App
app = JupyterDash(__name__)
app.layout = dash.html.Div(
[
dcc.Dropdown(
id="FirstDropdown",
options=[
{"label": "graph1", "value": "v1"},
{"label": "graph2", "value": "v2"},
{"label": "graph3", "value": "v3"},
{"label": "graph4", "value": "v4"},
{"label": "graph 5", "value": "v5"},
{"label": "g-form", "value": "v6"},
],
placeholder="Please choose an option",
value="v1",
),
dash.html.Div(
id="graph_container",
),
]
)
#app.callback(
Output("graph_container", "children"),
Input("FirstDropdown", "value"),
)
def select_graph(value):
if value in figs.keys():
return dash.dcc.Graph(figure=figs[value])
else:
return html.Iframe(
width="640px",
height="947px",
src="https://docs.google.com/forms/d/e/1FAIpQLSfkIgHkKlD5Jl4ewfWpA8y9D65UbhdrvZ0k7qXOBI7uFN1aNA/vi ewform?embedded=true",
)
app.run_server(mode="inline")

Filtering a column on Dash dataTable based on a list

I am very new to Dash. I have made a dataTable that includes several columns. These columns can be filtered and sorted. However, one problem with the filtering is that I cannot filter based on a list (like pandas .loc) e.g. if I want to filter the countries based on a list (say, ['India', 'United States']), the filter does not work. I have previously checked the advanced filtering here and found that I can use || operators; however,this would not be a good choice if the list is more than 4 or 5.
Here's the code:
import dash
from dash.dependencies import Input, Output
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import json
df = pd.read_csv(
'https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div(id='heading-users', children='Users\' Country details', style={
'textAlign': 'center', 'font-family': 'Helvetica'}),
dash_table.DataTable( # users
id='datatable-users',
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns
],
data=df.to_dict('records'),
editable=True,
filter_action="native",
sort_action="native",
sort_mode="multi",
column_selectable="single",
row_selectable="multi",
row_deletable=True,
selected_columns=[],
selected_rows=[],
page_action="native",
page_current=0,
page_size=20,
export_format='csv'
),
html.Div(id='datatable-users-container')
])
#app.callback(
Output('datatable-users-container', "children"),
Input('datatable-users', "derived_virtual_data"),
Input('datatable-users', "derived_virtual_selected_rows"))
def update_graphs(rows, derived_virtual_selected_rows):
if derived_virtual_selected_rows is None:
derived_virtual_selected_rows = []
dff = df if rows is None else pd.DataFrame(rows)
colors = ['#7FDBFF' if i in derived_virtual_selected_rows else '#0074D9'
for i in range(len(dff))]
return [
dcc.Graph(
id=column,
figure={
"data": [
{
"x": dff["country"],
"y": dff[column],
"type": "bar",
"marker": {"color": colors},
}
],
"layout": {
"xaxis": {"automargin": True},
"yaxis": {
"automargin": True,
"title": {"text": column}
},
"height": 250,
"margin": {"t": 10, "l": 10, "r": 10},
},
},
)
# check if column exists - user may have deleted it
# If `column.deletable=False`, then you don't
# need to do this check.
for column in ["pop", "lifeExp", "gdpPercap"] if column in dff
]
if __name__ == '__main__':
app.run_server(debug=True)
From that link - The 'native' filter function doesn't support 'OR' operations within a single column. Assign filter_action="custom" then create a callback to update the table children. See the 'Back-End Filtering section of that link.
You'll need to grab the filter query string in a callback and decompose to extract the column name and query string. With that you can query the pandas dataframe and return the results in a callback. I don't have the code for "OR" functionality but found some I used that can query pandas once you have the input values
def filter_df(df, filter_column, value_list):
conditions = []
for val in value_list:
conditions.append(f'{filter_column} == "{val}"')
query = ' or '.join(conditions)
print(f'querying with: {query}')
return df.query(query_expr)
filter_df(df, 'country', ['Albania', 'Algeria'])

Export Plotly Dash datatable output to a CSV by clicking download link

Hi Anyone able to help advise?
I have an issue trying to export the data being populated from data table filtered from drop down selection upon clicking on download link to a CSV file.
Error gotten after clicking on the Download Link
csv_string = dff.to_csv(index=False, encoding='utf-8')
AttributeError: 'str' object has no attribute 'to_csv'
And the file that was downloaded is a file containing html code.
Code snippets below
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output,State
import plotly.graph_objs as go
import dash_table
import dash_table_experiments as dt
from urllib.parse import quote
import flask
import pandas as pd
import numpy as np
import pyodbc
app.layout = html.Div([
html.H3("Sales Summary Report"),
dcc.Graph(
figure={
"data": [
{
"x": df["Sales_RANGE"],
"y": df['count'],
"name":'No of Cust',
"type": "bar",
"marker":{'color':'rgba(26, 118, 255, 0.5)',
#'line':{
# 'color':'rgb(8,48,107)',
# 'width':1.5,
# }
}
}
],
"layout": {
"xaxis": {"automargin": True},
"yaxis": {
"automargin": True,
# "title": {"text": column}
},
"height": 250,
"margin": {"t": 10, "l": 10, "r": 10},
},
},
)
,
html.Label(["Select Sales range to view",
dcc.Dropdown(
id="SalesRange",
style={'height': '30px', 'width': '55%'},
options=[{'label': i,
'value': i
} for i in Sales_Range_Options],
value='All'
)
]),
#TABLE
html.H5("Details"),
html.Div(id='detailsresults') ,
html.A('Download Data',
id='download-link',
download="rawdata.csv",
href="",
target="_blank"
)
])
def generate_table(dataframe):
'''Given dataframe, return template generated using Dash components
'''
return html.Div( [dash_table.DataTable(
#id='match-results',
data=dataframe.to_dict('records'),
columns=[{"name": i, "id": i} for i in dataframe.columns],
editable=False
),
html.Hr()
])
#app.callback(
Output('detailsresults', 'children'),
[
Input('SalesRange', 'value'),
]
)
def load_results(SalesRange):
if SalesRange== 'All':
return generate_table(df)
else:
results = df[df['SALES_RANGE'] == SalesRange]
return generate_table(results)
#app.callback(
dash.dependencies.Output('download-link', 'href'),
[dash.dependencies.Input('SalesRange', 'value')])
def update_download_link(SalesRange):
dff = load_results(SalesRange)
csv_string = dff.to_csv(index=False, encoding='utf-8')
csv_string = "data:text/csv;charset=utf-8,%EF%BB%BF" + quote(csv_string)
return csv_string
CSV export is officially supported by dash_table.DataTable. You simply need to specify export_format='csv' when you build the table:
dash_table.DataTable(
id="table",
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("records"),
export_format="csv",
)
Here's a complete example app.py that you can run:
import dash
import dash_table
import dash_html_components as html
import pandas as pd
df = pd.DataFrame(
[
["California", 289, 4395, 15.3, 10826],
["Arizona", 48, 1078, 22.5, 2550],
["Nevada", 11, 238, 21.6, 557],
["New Mexico", 33, 261, 7.9, 590],
["Colorado", 20, 118, 5.9, 235],
],
columns=["State", "# Solar Plants", "MW", "Mean MW/Plant", "GWh"],
)
app = dash.Dash(__name__)
server = app.server
app.layout = dash_table.DataTable(
id="table",
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("records"),
export_format="csv",
)
if __name__ == "__main__":
app.run_server(debug=True)
You will see a button above the table:
I believe your answer is like the following:
#app.server.route('/dash/urlToDownload')
def download_csv():
return send_file('output/downloadFile.csv',
mimetype='text/csv',
attachment_filename='downloadFile.csv',
as_attachment=True)
You may take a look at this link for more information:
Allowing users to download CSV on click

Categories