我可以通过使用行索引以外的其他方式访问 selected_rows.data 吗?

问题描述 投票:0回答:1

我一直在努力创建一个过滤器,让我在另一个表中显示 selected_rows。我正在使用这个代码

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

#Define sample dataframes with the same columns
df1 = pd.DataFrame({'Category': ['A', 'B', 'C'], 'Value': [1, 2, 3], 'tipo': ['Direita','Esquerda','Direita']})
df2 = pd.DataFrame({'Category': ['D', 'E', 'F'], 'Value': [5, 6, 7], 'tipo': ['Esquerda','Direita','Esquerda']})


lista_filtros = df1['tipo'].unique()

# Define Dash app
app = dash.Dash(__name__)
app.config.suppress_callback_exceptions = True

# Define dropdown options
dropdown_options = [{'label': 'Dataframe 1', 'value': 'df1'},
                    {'label': 'Dataframe 2', 'value': 'df2'}]

# Define layout
app.layout = html.Div([
    dcc.Dropdown(
        id='dropdown',
        options=dropdown_options,
        value='df1'
    ),
    dcc.Checklist(
        id='type-checklist',
        options=[{'label': i, 'value': i} for i in lista_filtros] + [{'label': 'All', 'value': 'All'}],
        value=['All']
    ),
    html.Br(),
    DataTable(
        id='table',
        row_selectable='multi',
        selected_rows=[],
        page_size=15
    ),
    html.Button('Submit', id='submit-button', n_clicks=0),
    dcc.Store(id='selected-rows', storage_type='session'),
    html.Br(),
    html.Div([
        DataTable(
            id='selected-data',
            columns=[{'name': 'Category', 'id': 'Category'}, {'name': 'Value', 'id': 'Value'}],
            page_size=5,
            row_deletable= True,
        )
    ], id='selected-data-container', style={'display': 'none'})
])

# Define callback to update table based on dropdown selection and type checklist
@app.callback(
    Output('table', 'data'),
    [Input('dropdown', 'value'), Input('type-checklist', 'value')]
)
def update_table(selected_value, selected_type):
    if selected_value == 'df1':
        df = df1
    elif selected_value == 'df2':
        df = df2
    else:
        return []

    all_selected = 'All' in selected_type
    if all_selected:
        return df.to_dict('records')
    else:
        filtered_df = df[df['tipo'].isin(selected_type)]
        # preserve original order of rows
        filtered_df = filtered_df.set_index('tipo')
        filtered_df = filtered_df.loc[selected_type]
        filtered_df = filtered_df.reset_index()
        return filtered_df.to_dict('records')


# Define callback to store selected rows in dcc.Store
@app.callback(
    Output('selected-rows', 'data'),
    [Input('submit-button', 'n_clicks')],
    [State('table', 'selected_rows')]
)
def store_selected_rows(n_clicks, selected_rows):
    if selected_rows:
        return selected_rows

# Define callback to update selected data table visibility and content
@app.callback(
    [Output('selected-data-container', 'style'),
     Output('selected-data', 'columns'),
     Output('selected-data', 'data')],
    [Input('selected-rows', 'data')],
    [State('selected-data', 'data'),
     State('dropdown', 'value')]
)
def update_selected_data(selected_rows, stored_data, selected_value):
    if selected_rows:
        # get selected rows from selected dataframe
        if selected_value == 'df1':
            selected_df = df1.iloc[selected_rows]
        elif selected_value == 'df2':
            selected_df = df2.iloc[selected_rows]
        else:
            selected_df = pd.DataFrame()
        # add new selected data to stored data
        if stored_data is not None:
            stored_df = pd.DataFrame(stored_data)
            stored_df = stored_df.append(selected_df, ignore_index=True)
            stored_data = stored_df.to_dict('records')
        else:
            stored_data = selected_df.to_dict('records')
        # get columns for selected data table
        selected_columns = [{'name': i, 'id': i} for i in selected_df.columns]
        # return updated values
        return {'display': 'block'}, selected_columns, stored_data
    else:
        # return default values
        return {'display': 'none'}, [], None

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

在我为“selected_type”清单选择“all”以外的参数之前,仪表板运行良好。

这是因为我对“selected_rows.data”参数返回给我的索引有问题。

例如,如果我使用“right”过滤器,我将看到的是“category = B”,它是我的“id = table”过滤后的索引0。

但是,当我按下“提交”按钮时,我的函数在过滤之前使用原始表中的索引 0,因此我收到数据“Category = A”。

这更像是一个 Python 问题而不是 Dash 问题,但是回调的使用让我很难解决,当我尝试在“updated_selected_data”函数中重新创建一个新的过滤数据帧时导致各种错误。

我只需要我的表准确反映我在上一个表中看到的数据,这可以很容易地使用索引以外的任何参数来完成。关于如何解决这个问题的任何想法?

python-3.x callback plotly-dash
1个回答
0
投票

我认为您不需要使用 dcc.Store 来返回 selected_rows 并且您应该更改为:

html.Div([
        DataTable(
            id='selected-data',
            columns=[{'name': 'Category', 'id': 'Category'}, {'name': 'Value', 'id': 'Value'}],
            page_size=5,
            row_deletable= True,
        )
    ], id='selected-data-container', style={'display': 'none'})
])

至:

html.Div(id='selected-data-container')

然后返回新的 DataTable 到这个 DIv.

完整代码:

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

#Define sample dataframes with the same columns
df1 = pd.DataFrame({'Category': ['A', 'B', 'C'], 'Value': [1, 2, 3], 'tipo': ['Direita','Esquerda','Direita']})
df2 = pd.DataFrame({'Category': ['D', 'E', 'F'], 'Value': [5, 6, 7], 'tipo': ['Esquerda','Direita','Esquerda']})


lista_filtros = df1['tipo'].unique()

# Define Dash app
app = dash.Dash(__name__)
app.config.suppress_callback_exceptions = True

# Define dropdown options
dropdown_options = [{'label': 'Dataframe 1', 'value': 'df1'},
                    {'label': 'Dataframe 2', 'value': 'df2'}]

# Define layout
app.layout = html.Div([
    dcc.Dropdown(
        id='dropdown',
        options=dropdown_options,
        value='df1'
    ),
    dcc.Checklist(
        id='type-checklist',
        options=[{'label': i, 'value': i} for i in lista_filtros] + [{'label': 'All', 'value': 'All'}],
        value=['All']
    ),
    html.Br(),
    DataTable(
        id='table',
        row_selectable='multi',
        selected_rows=[],
        page_size=15
    ),
    html.Button('Submit', id='submit-button', n_clicks=0),
    dcc.Store(id='selected-rows', storage_type='session'),
    html.Br(),
    html.Div(id='selected-data-container')
])

# Define callback to update table based on dropdown selection and type checklist
@app.callback(
    Output('table', 'data'),
    [Input('dropdown', 'value'), 
     Input('type-checklist', 'value')]
)
def update_table(selected_value, selected_type):
    if selected_value == 'df1':
        df = df1
    elif selected_value == 'df2':
        df = df2
    else:
        return []

    all_selected = 'All' in selected_type
    if all_selected:
        return df.to_dict('records')
    else:
        filtered_df = df[df['tipo'].isin(selected_type)]
        # preserve original order of rows
        filtered_df = filtered_df.set_index('tipo')
        filtered_df = filtered_df.loc[selected_type]
        filtered_df = filtered_df.reset_index()
        return filtered_df.to_dict('records')
@app.callback(
    Output('selected-data-container', 'children'),
    [Input('submit-button', "n_clicks"),
     State('dropdown', 'value'),
     State('table', 'selected_rows')]
)
def update_bar(n_clicks, selected_value, slctd_rows):
    if selected_value == 'df1':
        df = df1
        df_filterd = df1[df1.index.isin(slctd_rows)]
    elif selected_value == 'df2':
        df = df2
        df_filterd = df2[df2.index.isin(slctd_rows)]
    return html.Div([
        DataTable(
        id='table2',
        data=df_filterd.to_dict('records')
    ),
    ])
    
# Run the app
if __name__ == '__main__':
    app.run_server(debug=False)

请检查是否是您需要的。

© www.soinside.com 2019 - 2024. All rights reserved.