Возвращать Pandas DataFrame в качестве data_table из обратного вызова с Plotly Dash для Python - PullRequest
0 голосов
/ 20 марта 2019

Я хотел бы прочитать файл .csv и вернуть функцию groupby в качестве обратного вызова, которая будет отображаться в виде простой таблицы данных с библиотекой "dash_table". Полезный ответ @ Lawliet показывает, как это сделать с помощью библиотеки "dash_table_experiment". Вот где я застрял:

import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Input, Output, State

df = pd.read_csv(
        'https://gist.githubusercontent.com/chriddyp/'
        'c78bf172206ce24f77d6363a2d754b59/raw/'
        'c353e8ef842413cae56ae3920b8fd78468aa4cb2/'
        'usa-agricultural-exports-2011.csv')

app = dash.Dash()
application = app.server

app.layout = html.Div([
    dash_table.DataTable(
        id = 'datatable',        
    ),

    html.Div([
        html.Button(id='submit-button',                
                children='Submit'
    )
    ]),    

])

@app.callback(Output('datatable','data'),
            [Input('submit-button','n_clicks')],
                [State('submit-button','n_clicks')])

def update_datatable(n_clicks,csv_file):            
    if n_clicks:                            
        dfgb = df.groupby(['state']).sum()
        return dfgb.to_dict('rows')

if __name__ == '__main__':
    application.run(debug=False, port=8080)

Ответы [ 2 ]

4 голосов
/ 22 марта 2019

Когда вы пытаетесь зарегистрировать компонент обратного вызова Output как DataTable, все обязательные / обязательные атрибуты для компонента DataTable должны быть обновлены в обратном вызове и возвращены. В вашем коде вы обновляете только DataTable.data, а не DataTable.column, одним простым способом является возврат всего компонента Datatable, который предварительно заполнен всеми необходимыми значениями атрибутов.

Вот пример,

import dash_html_components as html
import dash_core_components as dcc
import dash
import dash_table
import pandas as pd
import dash_table_experiments as dt

app = dash.Dash(__name__)

#data to be loaded
data = [['Alex',10],['Bob',12],['Clarke',13],['Alex',100]]
df = pd.DataFrame(data,columns=['Name','Mark'])

app.layout = html.Div([
    dt.DataTable(
            rows=df.to_dict('records'),
            columns=df.columns,
            row_selectable=True,
            filterable=True,
            sortable=True,
            selected_row_indices=list(df.index),  # all rows selected by default
            id='2'
     ),
    html.Button('Submit', id='button'),
    html.Div(id="div-1"),
])


@app.callback(
    dash.dependencies.Output('div-1', 'children'),
    [dash.dependencies.Input('button', 'n_clicks')])
def update_output(n_clicks):

    df_chart = df.groupby('Name').sum()

    return [
        dt.DataTable(
            rows=df_chart.to_dict('rows'),
            columns=df_chart.columns,
            row_selectable=True,
            filterable=True,
            sortable=True,
            selected_row_indices=list(df_chart.index),  # all rows selected by default
            id='3'
        )
    ]

if __name__ == '__main__':
    app.run_server(debug=True)

Похоже, dash-table-experiments устарела.

Редактировать 1: Вот один из способов достижения этого с помощью dash_tables

import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table as dt
from dash.dependencies import Input, Output, State

df = pd.read_csv(
        'https://gist.githubusercontent.com/chriddyp/'
        'c78bf172206ce24f77d6363a2d754b59/raw/'
        'c353e8ef842413cae56ae3920b8fd78468aa4cb2/'
        'usa-agricultural-exports-2011.csv')

app = dash.Dash()
application = app.server

app.layout = html.Div([
    dt.DataTable(
        id = 'dt1', 
        columns =  [{"name": i, "id": i,} for i in (df.columns)],

    ),
    html.Div([
        html.Button(id='submit-button',                
                children='Submit'
        )
    ]),    

])

@app.callback(Output('dt1','data'),
            [Input('submit-button','n_clicks')],
                [State('submit-button','n_clicks')])

def update_datatable(n_clicks,csv_file):            
    if n_clicks:                            
        dfgb = df.groupby(['state']).sum()
        data_1 = df.to_dict('rows')
        return data_1

if __name__ == '__main__':
    application.run(debug=False, port=8080)

Другой способ: вернуть целое DataTable

import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table as dt
from dash.dependencies import Input, Output, State

df = pd.read_csv(
        'https://gist.githubusercontent.com/chriddyp/'
        'c78bf172206ce24f77d6363a2d754b59/raw/'
        'c353e8ef842413cae56ae3920b8fd78468aa4cb2/'
        'usa-agricultural-exports-2011.csv')

app = dash.Dash()
application = app.server

app.layout = html.Div([
    html.Div(id="table1"),

    html.Div([
        html.Button(id='submit-button',                
                children='Submit'
    )
    ]),    

])

@app.callback(Output('table1','children'),
            [Input('submit-button','n_clicks')],
                [State('submit-button','n_clicks')])

def update_datatable(n_clicks,csv_file):            
    if n_clicks:                            
        dfgb = df.groupby(['state']).sum()
        data = df.to_dict('rows')
        columns =  [{"name": i, "id": i,} for i in (df.columns)]
        return dt.DataTable(data=data, columns=columns)


if __name__ == '__main__':
    application.run(debug=False, port=8080)


Я ссылался на этот пример: https://github.com/plotly/dash-table/blob/master/tests/cypress/dash/v_copy_paste.py#L33

2 голосов
/ 26 марта 2019

Вы почти сделали это только с незначительными изменениями в update_datatable, оно должно работать нормально (не проверено):

def update_datatable(n_clicks,csv_file):            
    if n_clicks:                            
        dfgb = df.groupby(['state']).sum()
        return html.Div([dash_table.DataTable(
                data=dfgb.to_dict('rows'),
                columns=[{'name': i, 'id': i} for i in dfgb.columns],
                style_header={'backgroundColor': "#FFD700",
                              'fontWeight': 'bold',
                              'textAlign': 'center',},
                style_table={'overflowX': 'scroll'},  
                style_cell={'minWidth': '180px', 'width': '180px',
                        'maxWidth': '180px','whiteSpace': 'normal'},                        
                         filtering=True,
                 row_selectable="multi",
                 n_fixed_rows=1),
               html.Hr()
        ])
...