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).
Divfilled with aDataTable()to anotherDiv(dataframe_output) in the first place. Doesn't it seem a little redundant? Try sending just theDataTable()to the placeholderDiv. Secondly, as the previous is just my intuition, the wayDataTable()'s are normally populated currently is via creating an empty one with the right column names/id's preset in, and then sending to thatDataTable()'sdataproperty a pandas dataframe expressed in dict() form - ex.df.to_dict(orient='rows').... returned a value which is not JSON serializableis really as simple as it looks - make sure all your callbacks only send normal outputs to wherever they're needed (and I suspect sending aDivis what confused Dash). Lastly, if you want to keep your dataframe in a temporary location for storing purposes, as FBruzzesi shows, he describes the old way users had to store memory in their apps, which still works, but you should look into a newer component that was created to help do that, community.plot.ly/t/announcing-the-storage-component/13758 .