save a modified dash datatable to dataframe - python

I'm new to dash and I'm struggling to save the edits made on the dash data table back to a data frame
here is my code of the data table
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
import sqlalchemy
app = dash.Dash(__name__)
engine = sqlalchemy.create_engine('mysql+pymysql://root:#127.0.0.1:3306/sfp')
df = pd.read_sql_table("base_case",engine)
app.layout = html.Div([
html.Div([
dcc.Input(
id='adding-rows-name',
placeholder='Enter a column name...',
value='',
style={'padding': 10}
),
html.Button('Add Column', id='adding-rows-button', n_clicks=0)
], style={'height': 50}),
dash_table.DataTable(
id='adding-rows-table',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict('records'),
editable=True,
row_deletable=True
),
html.Button('Add Row', id='editing-rows-button', n_clicks=0),
])
if __name__ == '__main__':
app.run_server(debug=True)
is there any solution to do that ?

You need a callback for it and this is an example how you could do it:
import dash
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('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
nmb_clicks = 0
app.layout = html.Div([
dcc.Store(id='click-memory', data = {'nmb_clicks': nmb_clicks}),
html.Div([
dcc.Input(
id='adding-rows-name',
placeholder='Enter a column name...',
value='',
style={'padding': 10}
),
html.Button('Add Column', id='adding-columns-button', n_clicks=nmb_clicks)
], style={'height': 50}),
dash_table.DataTable(
id='adding-rows-table',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict('records'),
editable=True,
row_deletable=True
),
html.Button('Add Row', id='editing-rows-button', n_clicks=0),
])
#app.callback(dash.dependencies.Output('adding-rows-table', 'columns'),
[dash.dependencies.Input('adding-columns-button', 'n_clicks'),
dash.dependencies.Input('adding-rows-name', 'value')],
[dash.dependencies.State('click-memory', 'data')])
def update_dropdown(click, name, data):
if click != data['nmb_clicks']:
if name not in df.columns:
df[name] = [float('nan')] * len(df.index)
return [{"name": i, "id": i} for i in df.columns]
#app.callback(dash.dependencies.Output('click-memory', 'data'),
[dash.dependencies.Input('adding-columns-button', 'n_clicks')],
[dash.dependencies.State('click-memory', 'data')])
def on_data(click, data):
if click != nmb_clicks:
data['nmb_clicks'] = data['nmb_clicks'] + 1
return data
if __name__ == '__main__':
app.run_server(debug=True)
Note that you would need to fill the column with some meaningful values (now empty cell are being inserted).

Related

Sidebar with filters (dropdowns) in Plotly Dash

I am trying to program a sidebar with some filters but the callback update_output of this dropdown is not working (not throwing an error, just doing nothing).
I think it is because this dropdown is not in the main layout, because my layout is composed of the sidebar and a content. My dropdowns in this sidebar will be filters that will be applied to the dataframe that feeds the graphs of the dashboard and dashboard2 layouts.
My question is how or where should I program those callbacks to give functionality to my sidebar dropdowns?
sidebar = html.Div(
[
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P(
"Sidebar", className="lead"
),
dbc.Nav(
[
dbc.NavLink("Home", href="/", active="exact"),
dbc.NavLink("Page 1", href="/page-1", active="exact"),
dbc.NavLink("Page 2", href="/page-2", active="exact"),
],
vertical=True,
pills=True,
),
dcc.Dropdown(id='dropdown',value="City"),
html.Br(),
dcc.Dropdown(id='dropdown2',options=[])
],
style=SIDEBAR_STYLE,
)
content = html.Div(id="page-content", children=[], style=CONTENT_STYLE)
app.layout = html.Div([
dcc.Location(id="url"),
sidebar,
content
])
#app.callback(
Output('dropdown2', 'options'),
Input('dropdown', 'value')
)
def update_output(value):
return df[df["cities"].isin(value)]
#app.callback(
Output("page-content", "children"),
[Input("url", "pathname")]
)
def render_page_content(pathname):
if pathname == "/":
return dashboard.layout
elif pathname == "/page-1":
return dashboard.layout
elif pathname == "/page-2":
return dashboard2.layout
# return a 404 message when user tries to reach a different page
return dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname {pathname} was not recognised..."),
]
)
if __name__=='__main__':
app.run_server(debug=True, port=8000)
I find checklists to be better for this purpose. If you're open to using that instead of dropdown menu to filter your dataframe, then the complete snippet below will produce the following Plotly Dash App.
Complete code:
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import pandas as pd
import plotly.graph_objs as go
import numpy as np
import plotly.express as px
app = JupyterDash(external_stylesheets=[dbc.themes.SLATE])
df = px.data.stocks()
df = df.set_index('date')
controls = dbc.Card(
[
dbc.FormGroup(
[
dbc.Label("Checklist"),
dcc.Checklist(
id="column_select",
options=[{"label":col, "value": col} for col in df.columns],
value=[df.columns[0]],
labelStyle={'display': 'inline-block', 'width': '12em', 'line-height':'0.5em'}
),
],
),
],
body=True,
style = {'font-size': 'large'}
)
app.layout = dbc.Container(
[
html.H1("Dropdowns and checklists"),
html.Hr(),
dbc.Row([
dbc.Col([controls],xs = 4),
dbc.Col([
dbc.Row([
dbc.Col(dcc.Graph(id="graph"), style={'height': '420px'}),
])
]),
]),
],
fluid=True,
)
#app.callback(
Output("graph", "figure"),
[Input("column_select", "value"),],
)
def make_graph(cols):
fig = px.line(df, x = df.index, y = cols, template = 'plotly_dark')
return fig
app.run_server(mode='external', port = 8982)

In the dash app, can href be implemented in to the value within in dcc.Dropdown?

I am trying to build a dropdown page selector in a multi page dash app. The dropdown selection should generate an updated html depending on the user selection. The issue that I'm running in to is that I do not know how to use href within the value selection of dcc.Dropdown.
The code below is my current example that is not working.
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__, suppress_callback_exceptions=True)
server = app.server
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div([
html.H2('Equipment Maintenance & Repair Dashboard'),
html.Div([
dcc.Dropdown(id='page_dd',
options=[{'label': x, 'value': x} for x, y in page_info.items()])
])
])
])
if __name__ == '__main__':
app.run_server()
If I use dcc.Link instead of dcc.Dropdown, then the output is successful. See the example below, which properly changes the html following the user selection.
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__, suppress_callback_exceptions=True)
server = app.server
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div([
html.H2('Equipment Maintenance & Repair Dashboard'),
html.Div([
dcc.Link('Trend ', href='/apps/dispatch_trend'),
dcc.Link('Equipment ', href='/apps/equipment_overview')
])
])
])
if __name__ == '__main__':
app.run_server()
If you want the url to change based on the dropdown selection you need to create callback
#app.callback(Output("url", "pathname"), Input("page_dd", "value"))
def update_url_on_dropdown_change(dropdown_value):
return dropdown_value
Complete example
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Output, Input
app = dash.Dash(__name__, suppress_callback_exceptions=True)
server = app.server
app.layout = html.Div(
[
dcc.Location(id="url", refresh=False),
html.Div(
[
html.H2("Equipment Maintenance & Repair Dashboard"),
html.Div(
[
dcc.Dropdown(
id="page_dd",
options=[
{"label": "Trend", "value": "/apps/dispatch_trend"},
{
"label": "Equipment",
"value": "/apps/equipment_overview",
},
],
)
]
),
]
),
]
)
#app.callback(Output("url", "pathname"), Input("page_dd", "value"))
def update_url_on_dropdown_change(dropdown_value):
return dropdown_value
if __name__ == "__main__":
app.run_server()

Update values of a table by clicking on different parameters in the drop-down menu. Dash Python

Can someone help me to detect why when selecting the branchpoint parameter from the drop-down menu, the table value is not updated?
I understand that the drop-down menu options work as a button and pressing it should update the table values.
Thank you.
The code with jupyter notebook is the following one.
from dash.exceptions import PreventUpdate
from dash.dependencies import Input, Output
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import dash
from jupyter_dash import JupyterDash
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
from dash_table import DataTable, FormatTemplate
import cv2
import numpy as np
from mahotas.morph import hitmiss as hit_or_miss
app = JupyterDash(__name__)
server = app.server
percentage = FormatTemplate.percentage(2)
biomarkers = dbc.Card(
id = 'biomarkers',
children = [
dbc.CardHeader(html.H5(dbc.Badge("Ratios of biomarkers",className="m1-1"))),
dbc.CardBody(html.Div([
'Choose biomarker to calculate the ratio: ',
dcc.Dropdown(
id='biomarkers-options',
options=[
{'label': prop, 'value': prop}
for prop in [
'branchpoints', 'endpoints', 'mediumlength',
'totallength', 'specularoverlap']
]
),
html.Br(),
dash_table.DataTable(
columns = [
dict(id='parameter', name='Parameter'),
dict(id='rate', name='Rate', type='numeric', format=percentage)
],
data = [
dict(parameter='Branch Points', rate=0),
dict(parameter='End Points', rate=0),
dict(parameter='Medium Length', rate=0),
dict(parameter='Total Length', rate=0),
dict(parameter='Specular Overlap', rate=0)
],
editable=True
)
]),
),
],
# style={"width": "18rem"},
),
app.layout = html.Div(
[
dbc.Container(
children=[
dbc.Row([dbc.Col(biomarkers, md=4)]),
],
fluid= True,
),
]
)
#app.callback(
Output('loading-table', 'data'),
Input('biomarkers-options', 'value'),
State("loading-table", "data")
)
def loading_bp(value, table):
if value == 'branchpoints':
calcperbranchhem1=(50/(20+40))
else:
calcperbranchhem1=(50/(20+40))
return html.Div([
dash_table.DataTable(
id='loading-table',
columns = [
dict(id='parameter', name='Parameter'),
dict(id='rate', name='Rate', type='numeric', format=percentage)
],
data = [
dict(parameter='Branch Points', rate=calcperbranchhem1),
dict(parameter='End Points', rate=0),
dict(parameter='Medium Length', rate=0),
dict(parameter='Total Length', rate=0),
dict(parameter='Specular Overlap', rate=0)
],
editable=True
)
])
if __name__ == '__main__':
# Run app and display result inline in the notebook
app.run_server(mode='inline', host="localhost",port=8053)
You have
State("loading-table", "data")
but no "loading-table"

Plotly Dash Update Drop Down from call back where data frame inside the call back

I am trying to update the drop-down menu from the data frame column value where my data frame is generated inside call back since I am taking user inputs and extracting some data from API.
I want to create a filter in the dropdown that's why I want that drop-down updated dynamically using the data frame column.
so in a call back I have df['name_id'] through which I want to update the segment dropdown.
I have taken the only important line to break in my code since the code is too lengthy:
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import datetime
import dash_table
import httplib2
import pandas as pd
import requests
import io
import time
from Dash_App.app import app
from dash.dependencies import Input, Output, State
from oauth2client import GOOGLE_REVOKE_URI, GOOGLE_TOKEN_URI, client
from oauth2client import client, GOOGLE_TOKEN_URI
from datetime import date, timedelta
from apiclient import discovery
row1 = html.Div(
[
dbc.Row([
dbc.Col([
dbc.Input(id="client_id",
type="text",
placeholder="Client ID",
style={'width': '150px'}, persistence=True,
persistence_type='memory'),
]),
], align="center"),
], style={'margin-top': 20, 'margin-left': -90}
)
row2 = html.Div([
dbc.Row([
dbc.Col([
dcc.Dropdown(
id='segment',
options=[{'label': i, 'value': i} for i in "what"],
multi=True,
style={'width': '250px'},
placeholder='Segment'),
]),
])
])
tab_2_layout = dbc.Container(children=[
row1,
html.Br(),
row2,
]
)
#app.callback(Output('output_div-ga', 'children'),
[Input('submit-button', 'n_clicks')],
[State('client_id', 'value'),
],
)
def ga_output(clicks, client_id):
if clicks is not None:
my_client_id = client_id
credentials = client.OAuth2Credentials(
access_token=None, # set access_token to None since we use a refresh token
client_id=my_client_id)
credentials.refresh(httplib2.Http()) # refresh the access token (optional)
http = credentials.authorize(httplib2.Http()) # apply the credentials
service_v3 = discovery.build('analytics', 'v3', http=http)
segments = service_v3.management().segments().list().execute()
df = pd.DataFrame(segments['items'])
df = df[['name', 'id']]
df['name_id'] = df.name.astype(str).str.cat(df.id.astype(str), sep=':')
return html.Div([dcc.Store('memory'),
dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i} for i in dff.columns],
data=dff.to_dict("rows"), persistence=True, persistence_type='memory',
export_format="csv",
),
])
I am able to solve this by generating form inside call back.
return html.Div([
dbc.Row([
dbc.Col([
dcc.Dropdown(
id='segment',
options=[{'label': i, 'value': i} for i in df['name_id'].unique()],
persistence=True, persistence_type='memory',
multi=True,
style={'width': '250px', 'margin-left': -250, 'margin-top': 10},
placeholder='Segment'),
]), ]), ])
What worked for me was to give each column that you want to edit an id, make it editable and then update the dropdown options in the DataTable. I also returned the whole DataTable in my callback.
app.callback(
Output("table-dropdown-container", "children"),
Input("input-data-table-id", "data"),
)(self.update_unlabelled_shops_table)
...
dt = (
dash_table.DataTable(
id='table-id',
data=df.to_dict("records"),
columns=[{"name": i, "id": i} if i != column_name else {"name": i, "id": i, "editable": True, "presentation": "dropdown"} for i in df.columns],
page_size=8,
dropdown={
column_name: {
"options": [
{"label": i, "value": i}
for i in df[column_name].unique()
]
},
},
),
)
return dt
except Exception as e:
print(e)
return [None]
And to create your div block.
def create_div(self):
return html.Div(
[
dash_table.DataTable(
id='table-id',
columns=[],
editable=True,
dropdown={},
),
html.Div(id="table-dropdown-container"),
]
)
Hope this helps somebody...

How do I return a dataframe from an app.callback with my as output as dbc.Table.from_dataframe

I am trying to have a table load upon clicking a search button, and provide ID/password. My output is a dbc.Table.from_dataframe which allows an df argument; however when I use this as my output property, I am getting an error.
Here are the available properties in "my_table":
['children', 'id', 'style', 'className', 'key', 'tag', 'size', 'bordered', 'borderless', 'striped', 'dark', 'hover', 'responsive', 'loading_state']
I read the docs here
https://dash-bootstrap-components.opensource.faculty.ai/l/components/table
I tried such using 'children' and that didn't work either. I know with dcc table I need to return a dictionary, however I thought with dbc.Table.from_dataframe I can return a dataframe.
#app.callback(Output('my_table', 'df' ),
[Input('search-button','n_clicks')],
[State('input-id', 'value'),
State('input-password', 'value')]
)
def search_fi(n_clicks, iuser, ipasw):
if n_clicks > 0:
df = pd.DataFrame(
{
"First Name": ["Arthur", "Ford", "Zaphod", "Trillian"],
"Last Name": ["Dent", "Prefect", "Beeblebrox", "Astra"],
}
return df
import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button('Table', id='table-but', n_clicks=0),
html.Div(id='container-button-basic')
])
#app.callback(
dash.dependencies.Output('container-button-basic', 'children'),
[dash.dependencies.Input('table-but', 'n_clicks')])
def search_fi(n_clicks):
if n_clicks > 0:
df = pd.DataFrame(
{
"First Name": ["Arthur", "Ford", "Zaphod", "Trillian"],
"Last Name": ["Dent", "Prefect", "Beeblebrox", "Astra"]
})
print(df)
return dbc.Table.from_dataframe(df)
if __name__ == '__main__':
app.run_server(debug=True)
or
https://plotly.com/python/table/ figure
Html dash table html-table
Example

Categories