Dash 数据表下拉过滤器

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

Dash DataTable 组件在列标题下提供自由文本过滤器。

如何将此过滤器替换为包含所有可供选择的唯一值的下拉过滤器?

Excel 中有现成的东西:

或者在 DataTables JavaScript 组件中进行一些简单的修改

我知道我可以在通过回调与 DataTable 交互的 DataTable 之外使用下拉过滤器,但我希望下拉过滤器成为 DataTable 列标题的一部分。从这个意义上说,我不想使用以下解决方案:在破折号中从下拉列表中过滤行后显示数据表

python plotly-dash
1个回答
4
投票

选项#1:使用 Dash 的内置 DataTable 下拉属性

答案更新:2023

import pandas as pd
import dash
from dash import Dash, Input, Output, dcc, html, dash_table, State

# Sample filter & data
place_holder = None
df_filter = pd.DataFrame(
    {
        "Person": [place_holder],
        "Age": [place_holder],
        "Gender": [place_holder],
        "Occupation": [place_holder],
    }
)
df_data = pd.DataFrame(
    {
        "Person": ["Alice", "Brian", "Chris", "David", "Emily"],
        "Age": [25, 30, 36, 25, 36],
        "Gender": ["Female", "Male", "Male", "Male", "Female"],
        "Occupation": ["Engineer", "Doctor", "Lawyer", "Artist", "Artist"],
    }
)


app = Dash(__name__)

app.layout = html.Div(
    [
        html.H1("DataTable with Header Dropdowns for Filtering"),
        html.H2("Filtering Table"),
        html.Div(
            [
                dash_table.DataTable(
                    id="table-filter",
                    columns=[
                        {"name": i, "id": i, "presentation": "dropdown"}
                        for i in df_filter.columns
                    ],
                    data=df_filter.to_dict("records"),
                    editable=True,
                    dropdown={
                        col: {
                            "options": [
                                {"label": str(i), "value": str(i)}
                                for i in df_data[col].unique()
                            ],
                        }
                        for col in df_data.columns
                    },
                )
            ]
        ),
        dash_table.DataTable(
            id="table-data",
            columns=[{"name": i, "id": i} for i in df_data.columns],
            data=df_data.to_dict("records"),
            style_table={"overflowX": "scroll"},
            css=[{"selector": "tr:first-child", "rule": "display: none",},],
        ),
        html.Div(id="table-output"),
    ],
    # NOTE The margin of 5% set here needs to match the CSS width set in custom.css
    #      and depends on the total number of columns (so that the filter table sits
    #      flush with the header-hidden data table below it being filtered).
    style={"textAlign": "center", "margin": "5%"},
)


# Callback for updating table based on dropdown selection
@app.callback(
    Output("table-data", "data"),
    [Input("table-filter", "data_timestamp")],
    [State("table-filter", "data"), State("table-data", "data")],
)
def update_table(timestamp, filter_rows, current_data):
    if timestamp is None:
        raise dash.exceptions.PreventUpdate

    data = df_data.copy()
    cols = data.columns

    for col, value in filter_rows[0].items():
        if value is not None:
            data = data[data.astype(str)[col] == value]

    return data.to_dict("records")


app.run_server(debug=True)

结果: 但请注意,目前无法为 Dash DataTables 中的下拉菜单设置

multi=True
(就像针对
dash.dcc.Dropdown
组件一样)。如果需要这种过滤功能,最好使用 Dash DataTables 的内置过滤功能,或者参见下面的选项 #2。

选项#2:在 Dash 数据表之外使用下拉菜单

import dash
import pandas as pd

from dash import dash_table as dt
from dash import dcc
from dash import html
from dash.dependencies import Input
from dash.dependencies import Output

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")

app = dash.Dash(__name__)

states = df.State.unique().tolist()

app.layout = html.Div(
    children=[
        dcc.Dropdown(
            id="filter_dropdown",
            options=[{"label": st, "value": st} for st in states],
            placeholder="-Select a State-",
            multi=True,
            value=df.State.values,
        ),
        dt.DataTable(
            id="table-container",
            columns=[{"name": i, "id": i} for i in df.columns],
            data=df.to_dict("records")
        )
    ]
)


@app.callback(
    Output("table-container", "data"), 
    Input("filter_dropdown", "value")
)
def display_table(state):
    dff = df[df.State.isin(state)]
    return dff.to_dict("records")


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

→ 选择红色 ❌ 至

Clear all

如果您不希望所选选项始终存在/显示

一种选择是将以下 CSS 添加到本地

./assets/custom.css
文件中:

.Select--multi .Select-value {
    display: none;
}

这将导致以下行为:

(您可以在下拉列表上方添加一些标题或其他内容,以指示“选择一个州”等)

注意:在此实现案例中,您可能需要将参数

row_deletable=True
添加到
dt.DataTable
。然而,我刚刚测试了这个,它不会自动用选项重新填充下拉列表,因此,需要发明更多代码来解决这个问题,我认为这是可能的。但你明白了。

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