Coolio2654
Coolio2654

Reputation: 1739

Python Dash: loading pandas dataframes into data table

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

Answers (6)

Jean-Francois T.
Jean-Francois T.

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

Mazeen Muhammed
Mazeen Muhammed

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

haydard
haydard

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

Jamie
Jamie

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

Coolio2654
Coolio2654

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

Peter Leimbigler
Peter Leimbigler

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

Related Questions