Reputation: 1739
I have been trying to build an app with Dash recently, but despite looking through the many guides, I simply cannot figure out how to import a pandas dataframe into Dash's data table (which is essentially a pandas dataframe, except web-hosted and reactive).
Most examples illustrate how to manually pick certain columns/rows taken from a dataframe which is already hardcoded within the example, like in here. However, in, my situation, the dataframe is built within my code (and pandas is the easiest way to do this), so I end up having to figure out a way to convert a pd.Dataframe()
into a dash_table.DataTable()
.
How can I make this work? Using the references, I’ve tried the following code to send a dict of my dataframe to dash_table.DataTable()
, but nothing displays.
My code:
## Imports
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Input, Output, State
import datetime as dt
import pandas as pd
import numpy as np
## Custom functions that creates the pandas dataframe
from twitter_functions import old_tweets
app = dash.Dash(dev_tools_hot_reload=True)
app.scripts.config.serve_locally = True
app.config['suppress_callback_exceptions'] = True
app.layout = html.Div(children=[
html.H3('Twitter App'),
dcc.Input('ScreenName_Input', type='text'),
html.Button(id='screenNames_submit_button', children='Submit'),
dash_table.DataTable(id='tweet_table')
])
@app.callback(
Output(component_id='tweet_table', component_property='data'),
[Input(component_id='screenNames_submit_button', component_property='n_clicks_timestamp')],
[State(component_id='ScreenName_Input', component_property='value')]
)
def display_tweets(submit_button, screen_names):
tweets = old_tweets(screen_names)
return tweets.to_dict(orient='records')
if __name__ == '__main__':
app.run_server(debug=True)
Upvotes: 21
Views: 51148
Reputation: 12920
Dash Bootstrap Components can provide a way to directly import from a DataFrame
:
https://dash-bootstrap-components.opensource.faculty.ai/docs/components/table/
import dash_bootstrap_components as dbc
import pandas as pd
df = pd.DataFrame(
{
"First Name": ["Arthur", "Ford", "Zaphod", "Trillian"],
"Last Name": ["Dent", "Prefect", "Beeblebrox", "Astra"],
}
)
table = dbc.Table.from_dataframe(df, striped=True, bordered=True, hover=True)
Upvotes: 1
Reputation: 31
Was working on sample codes and this worked for me , this example might help u with your Query
import pandas as pd
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import base64
import io
app = dash.Dash()
# app.scripts.config.serve_locally = True
# app.css.config.serve_locally = True
DF_GAPMINDER = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv'
)
DF_GAPMINDER = DF_GAPMINDER[DF_GAPMINDER['year'] == 2007]
DF_GAPMINDER.loc[0:20]
DF_SIMPLE = pd.DataFrame({
'x': ['A', 'B', 'C', 'D', 'E', 'F'],
'y': [4, 3, 1, 2, 3, 6],
'z': ['a', 'b', 'c', 'a', 'b', 'c']
})
dataframes = {'DF_GAPMINDER': DF_GAPMINDER,
'DF_SIMPLE': DF_SIMPLE}
def get_data_object(user_selection):
"""
For user selections, return the relevant in-memory data frame.
"""
return dataframes[user_selection]
app.layout = html.Div([
html.H4('DataTable'),
html.Label('Report type:', style={'font-weight': 'bold'}),
dcc.Dropdown(
id='field-dropdown',
options=[{'label': df, 'value': df} for df in dataframes],
value='DF_GAPMINDER',
clearable=False
),
dash_table.DataTable(id='table')
])
@app.callback([Output(component_id='table', component_property='data'),
Output(component_id='table', component_property='columns')],
[Input('field-dropdown', 'value')])
def update_table(user_selection):
"""
For user selections, return the relevant table
"""
df = get_data_object(user_selection)
columns = [{'name': col, 'id': col} for col in df.columns]
data = df.to_dict(orient='records')
return data, columns
app.run_server()
Upvotes: 1
Reputation: 101
Assuming your tweets function returns a dataframe, adding table columns as a second output to your callback should work.
@app.callback(
[Output(component_id='tweet_table', component_property='data'),
Output(component_id='tweet_table', component_property='columns')
[Input(component_id='screenNames_submit_button', component_property='n_clicks_timestamp')],
[State(component_id='ScreenName_Input', component_property='value')]
)
def display_tweets(submit_button, screen_names):
tweets = old_tweets(screen_names)
columns = [{'name': col, 'id': col} for col in tweets.columns]
data = tweets.to_dict(orient='records')
return data, columns
Upvotes: 10
Reputation: 301
Here is another solution that worked for me:
dt_col_param = []
for col in output_df.columns:
dt_col_param.append({"name": str(col), "id": str(col)})
dash_table.DataTable(
columns=dt_col_param,
data=output_df.to_dict('records')
)
My biggest problem was that my app kept throwing an exception on whatever I was trying to pass into the 'columns' argument for dash_table.DataTable(...).
Hopefully this will help with not having to hard-code anything.
Upvotes: 4
Reputation: 1739
After someone also replied to me on the plotly forums (thankfully), it seems the final answer is to pre-set one's Data Table with the columns of the pandas dataframe that is going to go into it at some point, like this,
dash_table.DataTable(
id='table',
columns=[
{'name': 'Column 1', 'id': 'column1'},
{'name': 'Column 2', 'id': 'column2'},
{'name': 'Column 3', 'id': 'column3'},
{'name': 'Column 4', 'id': 'column4'},
{'name': 'Column 5', 'id': 'column5'}]
)
, and then send in a dict of your pandas dataframe.
Upvotes: 17
Reputation: 11105
This is a bit of a long shot and untested, but based on https://community.plot.ly/t/dash-datatable-using-callbacks/6756, it seems Dash DataTables implicitly require an initial value if you're going to modify them via callback.
Try changing this line:
dash_table.DataTable(id='tweet_table')
To this:
dash_table.DataTable(id='tweet_table', rows=[{}])
Upvotes: 2