Pass Pandas Dataframe between functions using Upload component in Plotly Dash - python

I am working with an Excel workbook in plotly dash and I need to access the dataframe it returns so I can use it as an input to another function, I'm following this tutorial - https://dash.plotly.com/dash-core-components/upload
I've tried a couple of approaches, per this solution here - Is it possible to upload a csv file in Dash and also store it as a pandas DataFrame?
but neither are working. When I set df as a global variable, which i also know is not good practice, I'm getting an error in the app that it is not defined NameError: name 'df' is not defined
I've also tried to pass the df variable between the functions but am unclear on how to access it when the inputs to the function parse_contents are all coming from the dash html component.
Here is my current code, you should be able to execute it with any excel workbook.
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html, dash_table
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([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-data-upload'),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
global df #define data frame as global
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
print(io.BytesIO(decoded))
workbook_xl = pd.ExcelFile(io.BytesIO(decoded))
df = pd.read_excel(workbook_xl, sheet_name=0)
# print(df)
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
]), df
#app.callback(Output('output-data-upload', 'children'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
print(df)
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
if __name__ == '__main__':
app.run_server(debug=True)

After tireless googling and reading message board posts I realized this is basically impossible, at least the way I was thinking about it initially.
Although it may be technically possible to pass a dataframe between the functions is is very difficult and highly discourages in this framework as it needs to interact heavily with javascript on the front end.
The best way to achieve the result of passing a dataframe in Dash is using the dcc.Store component which stores the data as JSON in the browser - https://dash.plotly.com/dash-core-components/store
You can then return the data in a html.Div and pass it to a call back later in the code. To achieve this I made a few changes to my code. First adding a dcc.Store component in the app layout:
app.layout = html.Div([ # this code section taken from Dash docs https://dash.plotly.com/dash-core-components/upload
dcc.Store(id='stored-data', storage_type='session'),
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-div'),
html.Div(id='output-datatable'),
])
Next you should return the stored-data in a html.Div from the parse_contents() fuction:
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns],
page_size=15
),
dcc.Store(id='stored-data', data=df.to_dict('records')),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
Finally, write a new callback that will pass the new data as a JSON object and convert it to a dataframe there:
#app.callback(Output('output-div', 'children'),
Input('stored-data','data'))
def make_graphs(data):
# bar_fig = px.bar(data, x=data['variable'], y=data['value'])
print(data)
df_agg = pd.DataFrame(data)
print(df_agg)
return #dcc.Graph(figure=bar_fig)
Full working code here -
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import plotly.express as px
import pandas as pd
from read_workbook import *
suppress_callback_exceptions=True
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([ # this code section taken from Dash docs https://dash.plotly.com/dash-core-components/upload
dcc.Store(id='stored-data', storage_type='session'),
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-div'),
html.Div(id='output-datatable'),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
workbook_xl = pd.ExcelFile(io.BytesIO(decoded))
#aggregates all months data into a single data frame
def get_all_months(workbook_xl):
months = ['July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'June']
xl_file = pd.ExcelFile('data/DP Beh Data 2022-23.xlsm')
months_data = []
for month in months:
months_data.append(get_month_dataframe(xl_file, month))
return pd.concat(months_data)
df = get_all_months(workbook_xl)
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns],
page_size=15
),
dcc.Store(id='stored-data', data=df.to_dict('records')),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
#app.callback(Output('output-datatable', 'children'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
#app.callback(Output('output-div', 'children'),
Input('stored-data','data'))
def make_graphs(data):
# bar_fig = px.bar(data, x=data['variable'], y=data['value'])
print(data)
df_agg = pd.DataFrame(data)
print(df_agg)
return #dcc.Graph(figure=bar_fig)
if __name__ == '__main__':
app.run_server(debug=True)
I hope this helps some other poor soul with this issue as I know from my search for the answer that a lot of folks have ran into this.

Related

Dash Plotly, unable to download the processed excel file on button click

I'm trying to build small dash App that lets the user download an Excel that is generated through the following function:
import base64
import io
import dash
from dash.dependencies import Input, Output, State
from dash import dcc,html
import plotly.express as px
import pandas as pd
app = dash.Dash()
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([
html.H1('Convertion of FMS logdata to parced data'),
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.B('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-data-upload'),
html.Div(
[
html.Button("Download xlsx", id="btn"),
dcc.Download(id="download")])
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
df2 = pd.read_excel(io.BytesIO(decoded), skiprows=8, usecols=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11])
return html.Div([
html.P('Analog Input2 with Respect to Timestamp'),
dcc.Graph(
figure=px.scatter(df2, x="Speed", y="Longitude")),
])
#app.callback(Output('output-data-upload', 'children'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
if __name__ == '__main__':
app.run_server(debug=True)
from this script I can able to plot the graph but I am unable to download the excel file of processed data on button click how can i do that any suggestions.
i used this data this is my data i used https://docs.google.com/spreadsheets/d/1QqiiAPLu7xU2BVOy3K4m0cjLIv0HsmHrrKnZMilfjgk/edit?usp=sharing and following snippet i got
I think you're missing a callback, try adding the following:
#app.callback(
Output("download", "data"),
[Input("btn", "n_clicks")],
prevent_initial_call=True,
)
def func(n_clicks):
return dcc.send_data_frame(df2.to_csv, "mydf.csv")

Using Dash to upload a PDF and display pandas dataframe extracted from it

I am using a pdf to extract some data and convert it into pandas dataframe.
I'm using below code from dash tutorial to display the data on dash app. What I want to do next is be able to upload the pdf instead of predefining it in the code. I could find similar examples for csv but with pdf it doesn't work in the same way.
pdfFileObj = open('test.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)
#some operations on pdf to produce df1 and df2 using PyPDF2
app = Dash(__name__)
app.layout = html.Div([
html.H4('Some title'),
html.P(id='table_out'),
dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i}
for i in df1.columns],
data=df1.to_dict('records'),
style_cell=dict(textAlign='left'),
style_header=dict(backgroundColor="paleturquoise"),
style_data=dict(backgroundColor="lavender")
),
html.H4("Some title"),
html.P(id='table_out1'),
dash_table.DataTable(
id='table1',
columns=[{"name": i, "id": i}
for i in df2.columns],
data=df2.to_dict('records'),
style_cell=dict(textAlign='left'),
style_header=dict(backgroundColor="paleturquoise"),
style_data=dict(backgroundColor="lavender")
)
])
#app.callback(
Output('table_out', 'children'),
Input('table', 'active_cell'))
#app.callback(
Output('table_out1', 'children'),
Input('table1', 'active_cell'))
def update_graphs(active_cell):
if active_cell:
cell_data = df1.iloc[active_cell['row']][active_cell['column_id']]
cell_data2 = df2.iloc[active_cell['row']][active_cell['column_id']]
return cell_data, cell_data2
#return f"Data: \"{cell_data}\" from table cell: {active_cell}"
return "Click the table"
app.run_server(debug=True)
I've had success with the below code, which uses the tabula package to parse contents of a pdf into Pandas dataframe and display that in the app.
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output, State
import dash_table
import pandas as pd
import base64
import io
import tabula
app = dash.Dash()
# Callback to parse contents of a pdf
#app.callback(Output('pdf-viewer', 'data'),
Output('pdf-viewer', 'columns'),
Input('pdf-upload', 'contents'),
State('pdf-upload', 'filename'),
prevent_initial_call=True
)
def pdf_output(contents, filename):
if contents is not None:
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
#My pdf only has one page and one table with two columns
df = tabula.read_pdf(io.BytesIO(decoded), pages=1, pandas_options={'header': None})[0]
df.columns = ['Parameter', 'Value']
return df.to_dict('records'), [{"name": i, "id": i, 'editable':True} for i in df.columns]
#Upload component:
pdf_load = dcc.Upload(id='pdf-upload',
children=html.Div(['Drag and Drop or ', html.A('Select PDF files')]),
style={'width': '90%', 'height': '60px', 'lineHeight': '60px',
'borderWidth': '1px', 'borderStyle': 'dashed',
'borderRadius': '5px', 'textAlign': 'center', 'margin': '10px'},
)
#Table to view output from pdf:
pdf_table = dash_table.DataTable(id='pdf-viewer',
page_action='none',
fixed_rows={'headers': True},
style_table={'height': 500, 'overflowY': 'auto'},
style_header={'overflowY': 'auto'}
)
#Place into the app
app.layout = html.Div([html.H4('Some title'),
pdf_load,
html.Br(),
pdf_table
])
if __name__ == '__main__':
app.run_server(debug = False)
Output (no formatting applied) should look something like this:
Example dash

Not being able to display data table using Plotly Dash code for larger file size

I am using the following code (from Plotly Dash documentation)to display a data table after uploading an csv/xlsx file into the Dash app.
import base64
import datetime
import io
from jupyter_dash import JupyterDash
import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html, dash_table
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = JupyterDash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-data-upload'),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns],
page_size =15
),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
#app.callback(Output('output-data-upload', 'children'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
app.run_server(mode='external')
Strangely, for files with size (1mb - 2mb) I am being able to display the file but for a file of size 14mb (approx) I am not being able to do the same and it is just looking like this -
I have tried using the max_size property setting it to -1(infinite size) as well but it doesn't solve the problem. Is there any way to do the same using dash_uploader?

Uploading a CSV to Plotly Dash and rendering a bar plot based on a Pandas dataframe

I'm new to the Plotly Dash framework and have attempted to build a simple dashboard that:
Allows the user to upload a CSV file to analyze graphically.
Creates a Pandas data frame based on the file uploaded in step #1.
2a. Renders nothing if the CSV file (and resulting data frame) has not been selected.
Renders a basic bar plot (or scatter plot, heat map, etc.) based on the data contained in the aforementioned data frame.
The data in my CSV file looks similar to the following:
df = pd.DataFrame({'Make':['Ford', 'Ford', 'Ford', 'BMW', 'BMW', 'BMW', Mercedes', 'Mercedes', 'Mercedes'],
'Score':['88.6', '76.6', '100', '79.1', '86.8', '96.4', '97.3', '98.7', '98.5'],
'Dimension':['Speed', 'MPG', 'Styling', 'Speed', 'MPG', 'Styling', 'Speed', 'MPG', 'Styling'],
'Month':['Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19']})
My code is as follows:
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
import dash_table
import pandas as pd
app = dash.Dash()
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-data-upload'),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
#### How to get the x and y values DYNAMICALLY from the data frame to pass into the Bar() function? ####
dcc.Graph(
figure = go.Figure(data=[
go.Bar(name=df.columns.values[0], x=pd.unique(df['Make']), y=[88.6, 76.6, 100], text=[88.6, 76.6, 100], textposition='auto'),
go.Bar(name=df.columns.values[1], x=pd.unique(df['Make']), y=[92.5, 93.6, 93.4], text=[92.5, 93.6, 93.4], textposition='auto'),
go.Bar(name=df.columns.values[2], x=pd.unique(df['Make']), y=[99.1, 99.2, 95.9], text=[99.1, 99.2, 95.9], textposition='auto'),
])
),
html.Hr(),
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
#app.callback(Output('output-data-upload', 'children'),
[Input('upload-data', 'contents')],
[State('upload-data', 'filename'),
State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
if __name__ == '__main__':
app.run_server(debug=True)
I'm able to upload and view the contents of the CSV file.
However, the go.Bar() function has its x and y values 'hard-coded' in. They're not necessarily DYNAMIC (i.e. if the number of x variables changes, etc.).
How do I get Dash to build the bar plot based on the data in the CSV file that's uploaded using the parse_contents(contents, filename, date) function?
I tried to follow along in Using dash upload component to upload csv file and generate a graph, but was unable to implement that example successfully.
Thanks in advance for helping a newbie get this toy example working!
Here is the answer:
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import plotly.graph_objects as go
import dash_table
import pandas as pd
app = dash.Dash()
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-data-upload'),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
dcc.Graph(
figure = go.Figure(data=[
go.Bar(name=df.columns.values[0], x=pd.unique(df['Make']), y=df['Score'], text=df['Score'], textposition='auto'),
])
),
])
#app.callback(Output('output-data-upload', 'children'),
[Input('upload-data', 'contents')],
[State('upload-data', 'filename'),
State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
if __name__ == '__main__':
app.run_server(debug=True)

Dash(Python) - can't display dataframe in datatable after calculations

I'm reading a text file(.csv mostly) from dash_core_components.Upload. I had no problems printing the file that i've taken. But, problems arise when i do some calculations and try printing that.
and the error is:
dash.exceptions.InvalidCallbackReturnValue:
The callback for property `children`
of component `dataframe_output` returned a value
which is not JSON serializable.
In general, Dash properties can only be
dash components, strings, dictionaries, numbers, None,
or lists of those.
Here's what I've done and tried:
# importing required libraries
import dash
import dash_table
import pandas as pd
import dash_core_components as dash_core
import dash_html_components as dash_html
from dash.dependencies import Input, Output
# starting app layout
app.layout = dash_html.Div([
# upload button to take csv files
dash_core.Upload(id='upload_data',
children=dash_html.Div(['Drag and Drop or ',
dash_html.A('Select Files')
]),
style={'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
multiple=False),
# a 'Div' to return table output to
dash_html.Div(id='dataframe_output'),
])
# callback to take and output the uploaded file
#app.callback(Output('dataframe_output', 'children'),
[Input('upload_data', 'contents'),
Input('upload_data', 'filename')])
def update_output(contents, filename):
if contents is not None:
# reading the file
input_data = pd.read_csv(filename)
# creating a dataframe that has info about "data types", "count of nulls", "count of unique values"
info_dataframe = pd.concat([pd.DataFrame(input_data.dtypes, columns=["data_types"]),
pd.DataFrame(input_data.isna().sum(), columns=["count of blanks"]),
pd.DataFrame(input_data.nunique(), columns=["count of unique values"])
],
axis=1, sort=True)
# adding index as a row
info_dataframe.reset_index(level=0, inplace=True)
# returning it to 'Div'
return dash_html.Div([
dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i} for i in info_dataframe .columns],
# columns=[{"name": i, "id": i} for i in input_data.columns], # this works fine
data=info_dataframe .to_dict("rows"),
# data=input_data.to_dict("rows"), # this works fine
style_cell={'width': '50px',
'height': '30px',
'textAlign': 'left'}
)
])
# running the app now
if __name__ == '__main__':
app.run_server(debug=True, port=8050)
(I also want to save this to a text file after displaying on browser. how do i do that too).
This always worked for me - try using a hidden Div for storing json serialized dataframe
import dash
import dash_table
import pandas as pd
import dash_core_components as dash_core
import dash_html_components as dash_html
from dash.dependencies import Input, Output
import base64
import io
# starting app layout
app.layout = dash_html.Div([
# upload button to take csv files
dash_core.Upload(id='upload_data',
children=dash_html.Div(['Drag and Drop or ',
dash_html.A('Select Files')
]),
style={'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
multiple=False),
# Div to store json serialized dataframe
dash_html.Div(id='json_df_store', style={'display':'none'}),
# a 'Div' to return table output to
dash_html.Div(id='dataframe_output'),
])
#app.callback(Output('json_df_store', 'children'),
[Input('upload_data', 'contents'),
Input('upload_data', 'filename')])
def load_df(content, filename):
if content:
# Modify the read_csv callback part
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
input_data = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
info_dataframe = pd.DataFrame(data={
"data_types": input_data.dtypes,
"blanks_count": input_data.isna().sum(),
"unique_count": input_data.nunique()
})
# adding index as a row
info_dataframe.reset_index(level=0, inplace=True)
info_dataframe.rename(columns={'index':'col_name'}, inplace=True)
info_dataframe['data_types'] = info_dataframe['data_types'].astype(str)
return info_dataframe.to_json(date_format='iso', orient='split')
except Exception as e:
#print(e)
return pd.DataFrame(data={'Error': e}, index=[0]).to_json(date_format='iso', orient='split')
# callback to take and output the uploaded file
#app.callback(Output('dataframe_output', 'children'),
[Input('json_df_store', 'children')])
def update_output(json_df):
info_dataframe = pd.read_json(json_df, orient='split')
data = info_dataframe .to_dict("rows")
cols = [{"name": i, "id": i} for i in info_dataframe .columns]
child = dash_html.Div([
dash_table.DataTable(
id='table',
data=data,
columns=cols,
style_cell={'width': '50px',
'height': '30px',
'textAlign': 'left'}
)
])
return child
# running the app now
if __name__ == '__main__':
app.run_server(debug=True, port=8050)

Categories

Resources