问题
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).
回答1:
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)
来源:https://stackoverflow.com/questions/58990502/dashpython-cant-display-dataframe-in-datatable-after-calculations