You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Python Dash中能否实现类似Power BI Hierarchy Slicer的多字段过滤?

在Dash中实现类似PowerBI的层级切片器(Hierarchy Slicer)

针对你用4个联动下拉框筛选4级组织架构表格的场景,我们可以通过Dash组件组合+回调逻辑,实现和PowerBI Hierarchy Slicer类似的层级折叠/展开、联动筛选效果,具体实现方案如下:

核心思路

用dash-bootstrap-components.Accordion实现层级折叠/展开的容器,每个层级嵌套dcc.Checklist作为选择项,通过回调实现:

  • 父级选择后自动过滤子级可选范围
  • 子级选择时自动关联父级筛选逻辑
  • 多层级混合选择后实时过滤表格数据

完整实现代码

1. 依赖导入与数据准备

import dash
from dash import Dash, dcc, html, Input, Output, callback
import dash_bootstrap_components as dbc
import pandas as pd

# 模拟4级组织架构业务数据
data = [
    {"一级部门": "技术部", "二级部门": "后端组", "三级部门": "Java组", "四级部门": "电商业务线", "员工数": 20},
    {"一级部门": "技术部", "二级部门": "后端组", "三级部门": "Python组", "四级部门": "数据分析线", "员工数": 15},
    {"一级部门": "技术部", "二级部门": "前端组", "三级部门": "Web组", "四级部门": "官网项目", "员工数": 10},
    {"一级部门": "市场部", "二级部门": "品牌组", "三级部门": "新媒体组", "四级部门": "抖音运营", "员工数": 8},
    {"一级部门": "市场部", "二级部门": "营销组", "三级部门": "线下推广", "四级部门": "华东区域", "员工数": 12},
    {"一级部门": "人事部", "二级部门": "招聘组", "三级部门": "校招组", "四级部门": "2024届", "员工数": 5},
]
df = pd.DataFrame(data)

2. 构建层级切片器布局

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

# 封装层级切片器组件
def build_hierarchy_slicer():
    level1_options = [{"label": dept, "value": dept} for dept in df["一级部门"].unique()]
    return dbc.Accordion(
        [
            dbc.AccordionItem(
                [
                    dcc.Checklist(
                        id="level1-checklist",
                        options=level1_options,
                        value=[],
                        labelStyle={"display": "block", "margin-left": "10px"},
                    ),
                    html.Div(id="level2-container"),
                ],
                title="一级部门",
                item_id="level1",
            )
        ],
        start_collapsed=False,
        className="border rounded p-2",
    )

# 页面整体布局
app.layout = dbc.Container(
    [
        html.H3("组织架构层级筛选"),
        dbc.Row(
            [
                dbc.Col(build_hierarchy_slicer(), width=4),
                dbc.Col(dcc.Graph(id="filtered-table"), width=8),
            ]
        ),
    ],
    fluid=True,
    className="mt-4",
)

3. 实现层级联动回调

# 更新二级部门选项
@callback(
    Output("level2-container", "children"),
    Input("level1-checklist", "value"),
)
def update_level2(selected_level1):
    filter_df = df[df["一级部门"].isin(selected_level1)] if selected_level1 else df
    level2_options = [{"label": dept, "value": dept} for dept in filter_df["二级部门"].unique()]
    return dbc.Accordion(
        [
            dbc.AccordionItem(
                [
                    dcc.Checklist(
                        id="level2-checklist",
                        options=level2_options,
                        value=[],
                        labelStyle={"display": "block", "margin-left": "20px"},
                    ),
                    html.Div(id="level3-container"),
                ],
                title="二级部门",
                item_id="level2",
            )
        ],
        start_collapsed=True,
    )

# 更新三级部门选项
@callback(
    Output("level3-container", "children"),
    Input("level1-checklist", "value"),
    Input("level2-checklist", "value"),
)
def update_level3(selected_level1, selected_level2):
    filter_df = df.copy()
    if selected_level1:
        filter_df = filter_df[filter_df["一级部门"].isin(selected_level1)]
    if selected_level2:
        filter_df = filter_df[filter_df["二级部门"].isin(selected_level2)]
    if filter_df.empty:
        return html.Div()
    level3_options = [{"label": dept, "value": dept} for dept in filter_df["三级部门"].unique()]
    return dbc.Accordion(
        [
            dbc.AccordionItem(
                [
                    dcc.Checklist(
                        id="level3-checklist",
                        options=level3_options,
                        value=[],
                        labelStyle={"display": "block", "margin-left": "30px"},
                    ),
                    html.Div(id="level4-container"),
                ],
                title="三级部门",
                item_id="level3",
            )
        ],
        start_collapsed=True,
    )

# 更新四级部门选项
@callback(
    Output("level4-container", "children"),
    Input("level1-checklist", "value"),
    Input("level2-checklist", "value"),
    Input("level3-checklist", "value"),
)
def update_level4(selected_level1, selected_level2, selected_level3):
    filter_df = df.copy()
    if selected_level1:
        filter_df = filter_df[filter_df["一级部门"].isin(selected_level1)]
    if selected_level2:
        filter_df = filter_df[filter_df["二级部门"].isin(selected_level2)]
    if selected_level3:
        filter_df = filter_df[filter_df["三级部门"].isin(selected_level3)]
    if filter_df.empty:
        return html.Div()
    level4_options = [{"label": dept, "value": dept} for dept in filter_df["四级部门"].unique()]
    return dcc.Checklist(
        id="level4-checklist",
        options=level4_options,
        value=[],
        labelStyle={"display": "block", "margin-left": "40px"},
    )

4. 表格筛选回调

@callback(
    Output("filtered-table", "figure"),
    Input("level1-checklist", "value"),
    Input("level2-checklist", "value"),
    Input("level3-checklist", "value"),
    Input("level4-checklist", "value"),
)
def filter_table(selected_level1, selected_level2, selected_level3, selected_level4):
    filtered_df = df.copy()
    # 应用各层级筛选条件
    if selected_level1:
        filtered_df = filtered_df[filtered_df["一级部门"].isin(selected_level1)]
    if selected_level2:
        filtered_df = filtered_df[filtered_df["二级部门"].isin(selected_level2)]
    if selected_level3:
        filtered_df = filtered_df[filtered_df["三级部门"].isin(selected_level3)]
    if selected_level4:
        filtered_df = filtered_df[filtered_df["四级部门"].isin(selected_level4)]
    # 生成可视化表格
    return {
        "data": [
            {
                "type": "table",
                "header": {
                    "values": list(filtered_df.columns),
                    "fill": {"color": "#1f77b4"},
                    "font": {"color": "white", "size": 12}
                },
                "cells": {
                    "values": [filtered_df[col] for col in filtered_df.columns],
                    "fill": {"color": ["#f0f0f0", "#ffffff"]},
                    "font": {"size": 11}
                }
            }
        ],
        "layout": {"margin": {"l": 10, "r": 10, "t": 20, "b": 20}}
    }

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

优化建议

  • 添加全选/取消全选按钮:在每个层级的Checklist旁添加按钮,通过回调实现一键选择当前层级所有选项
  • 自定义样式:通过style或外部CSS调整折叠图标、选项间距、边框样式,让组件更贴近PowerBI的视觉风格
  • 组件封装:将层级生成逻辑封装为通用函数,支持动态适配不同层级数量的组织架构
  • 空值处理:优化空选择场景的提示,避免表格空白

内容的提问来源于stack exchange,提问作者dshefman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 22:45:45