# 工具C 功能按钮开发计划 V1.0 **文档版本**: V1.4 (Phase 2+ 缺失值填补功能开发版) **创建日期**: 2025-12-08 **最后更新**: 2025-12-10 **负责人**: AI开发团队 **项目状态**: ✅ Phase 1-2 已完成,7个核心功能 + NA处理优化 + Pivot优化 + 缺失值填补(开发完成,MICE待调试) --- ## 🔥 重要架构变更(2025-12-08) **决策**:功能按钮采用**预写Python函数**架构,而非动态代码生成。 **变更原因**: - ❌ 旧方案:动态拼接Python代码字符串 → 不稳定、有安全风险、难以测试 - ✅ 新方案:调用预写的Python函数 → 稳定、安全、高性能、易维护 **当前完成**(2025-12-08): - ✅ Python微服务:`operations/` 模块 - filter.py(高级筛选) - recode.py(数值映射) - binning.py(生成分类变量) - conditional.py(条件生成列) - dropna.py(删除缺失值) - compute.py(计算列) - pivot.py(长表转宽表) - ✅ Python微服务:7个API端点(`/api/operations/*`) - ✅ Node.js后端:`QuickActionService.ts`(7个执行方法) - ✅ Node.js后端:`QuickActionController.ts`(完整错误处理) - ✅ 前端UI:7个Dialog组件(完整交互界面) - ✅ 前端工具栏:7个功能按钮(已启用) - ✅ 删除:`QuickActionCodeGenerator.ts`(不再使用) **架构对比**: | 维度 | 旧方案 | ✅ 新方案 | |------|--------|---------| | 稳定性 | ⚠️ 字符串拼接易出错 | ✅ 预写函数经过测试 | | 安全性 | ⚠️ 有注入风险 | ✅ 无代码注入风险 | | 性能 | ⚠️ 需解析代码 | ✅ 直接调用函数 | | 可维护 | ⚠️ 后端拼接字符串 | ✅ Python集中管理 | | 可测试 | ❌ 难以测试 | ✅ 易于单元测试 | --- ## 📋 文档目录 - [1. 概述](#1-概述) - [2. 设计原则](#2-设计原则) - [3. 功能清单](#3-功能清单) - [4. 分期开发计划](#4-分期开发计划) - [5. 技术架构](#5-技术架构) - [6. 详细设计](#6-详细设计) - [7. 验收标准](#7-验收标准) --- ## 1. 概述 ### 1.1 背景 工具C当前已实现AI对话式数据清洗功能。为提升用户体验和操作效率,需要针对**高频、通用、标准化**的数据清洗操作开发功能按钮,实现**一键式操作**。 ### 1.2 目标 - ✅ 提升高频操作的效率(从"描述需求"到"一键点击") - ✅ 降低学习成本(直观的UI代替自然语言描述) - ✅ 保持灵活性(复杂需求仍可使用AI对话) - ✅ 符合医疗科研用户习惯(参考SPSS、Excel等专业工具) ### 1.3 适用场景 **功能按钮适合:** - 高频使用(每个数据集都需要) - 操作通用(不依赖特定业务规则) - 参数明确(可以通过UI配置) - 逻辑简单(1-3步即可完成) **AI对话适合:** - 低频使用(偶尔用一次) - 业务特定(规则各异) - 复杂逻辑(多步骤、多条件) - 探索性操作(需理解上下文) --- ## 2. 设计原则 ### 2.1 用户体验原则 1. **80/20法则**:用按钮解决80%的简单需求,用AI对话解决20%的复杂需求 2. **渐进式披露**:简单功能默认显示,复杂选项折叠/高级模式 3. **即时反馈**:提供预览功能,让用户在执行前看到结果 4. **可撤销性**:支持撤销(未来版本)或提供"创建副本"选项 ### 2.2 技术原则 1. **✅ 预写函数架构**:功能按钮调用预写的、经过测试的Python函数(而非动态生成代码) 2. **无状态设计**:每个操作独立,不依赖前序状态 3. **安全可靠**:预写函数经过充分测试和验证,无代码注入风险 4. **性能优先**:直接调用函数,避免代码解析开销,优化大数据集处理 --- ## 3. 功能清单 ### 3.1 按分组划分 | 分组 | 功能 | 优先级 | 开发状态 | |------|------|--------|---------| | **样本筛选** | 高级筛选器 | P0 | ✅ 已完成(+为空/不为空条件)| | **变量转换** | 数值映射(重编码)| P0 | ✅ 已完成(+NA处理选项)| | | 生成分类变量(分箱)| P0 | ✅ 已完成(+NA处理选项)| | | 条件生成列 | P0 | ✅ 已完成(+为空/不为空条件)| | | 生成新变量(计算列)| P1 | ✅ 已完成(方案B:安全列名映射)| | **数据清理** | 缺失值处理(删除+填补)| P0 | ✅ 已完成(6种简单填补+MICE,MICE待调试)| | | 去重 | P1 | ⏸️ 已移除(用户需求)| | **数据重塑** | 长表→宽表(Pivot)| P1 | ✅ 已完成(+保留未选列+原始列顺序)| | **高级功能** | 多重插补(MICE)| P0 | 🚧 已集成到缺失值处理(待调试)| **优先级说明**: - **P0**:核心功能,Phase 1-2 必须完成 - **P1**:重要功能,Phase 3 完成 - **P2**:增强功能,Phase 4 可选 ### 3.2 不开发的功能 | 功能 | 原因 | |------|------| | 清理列名 | 暂不开发(用户需求) | | 宽表→长表 | 低频需求,暂不开发 | | 数据透视表 | 超出MVP范围 | | 统计分析 | 属于统计分析模块,非数据清洗 | --- ## 4. 分期开发计划 ### Phase 1:核心功能(Week 1,预计5天)✅ 已完成 **目标**:解决最高频的3个需求 | 功能 | 工作量 | 状态 | 验收标准 | |------|--------|------|---------| | 1. 高级筛选器 | 2天 | ✅ 完成 | 支持多条件AND/OR,实时预览 | | 2. 数值映射(重编码)| 1.5天 | ✅ 完成 | 自动提取唯一值,支持批量映射 | | 3. 生成分类变量(分箱)| 1.5天 | ✅ 完成 | 支持自定义切点、等宽、等频 | **里程碑**:✅ Week 1完成,3个核心功能可用(2025-12-08) --- ### Phase 2:条件生成+清理(Week 2,预计5天)✅ 已完成 **目标**:解决复杂条件逻辑需求 | 功能 | 工作量 | 状态 | 验收标准 | |------|--------|------|---------| | 4. 条件生成列 | 2天 | ✅ 完成 | 支持多条件IF-THEN规则 | | 5. 删除缺失值 | 1天 | ✅ 完成 | 支持按行/列删除,预览影响 | | 6. 去重 | 1天 | ⏸️ 暂不开发 | 用户决定暂不开发 | | 7. 计算列 | 1天 | ✅ 完成 | 公式构建器,支持常用函数 | | 8. Pivot(长→宽表)| 1天 | ✅ 完成 | 支持多值列转换,聚合选项 | **里程碑**:✅ Week 2完成,7个核心功能可用(2025-12-08) --- ### Phase 3:数据重塑+填补(Week 3-4,预计8天) **目标**:支持复杂数据转换 | 功能 | 工作量 | 负责人 | 验收标准 | |------|--------|--------|---------| | 8. 长表→宽表(Pivot)| 2天 | 前端+后端 | 支持多值列转换 | | 9. 生成新变量(计算列)| 2天 | 前端+后端 | 公式构建器,支持常用函数 | | 10. 缺失值填补 | 1.5天 | 前端+后端 | 支持均值/中位数/分组填补 | | 11. 多重插补(MICE)| 1.5天 | Python微服务 | 集成sklearn,支持基础MICE | | 12. 测试+文档 | 1天 | 全员 | 完成用户手册 | **里程碑**:Week 4结束,所有P0/P1功能完成 --- ### Phase 4:优化+增强(Week 5+,持续迭代) - ✅ 性能优化(大数据集>10万行) - ✅ 批量操作(批量重编码、批量删除列等) - ✅ 操作历史(查看/回退历史操作) - ✅ 保存为模板(常用操作保存为快捷方式) - ✅ 数据验证(自动检查数据质量) --- ## 5. 技术架构 ### 5.1 ✅ 整体架构(预写函数方案) **架构决策**:功能按钮使用**预写Python函数**,而非动态生成代码,确保稳定性和性能。 ``` ┌─────────────────────────────────────────────────┐ │ 前端 (React + Ant Design) │ │ ┌─────────────────────────────────────────┐ │ │ │ 工具栏组件 │ │ │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │ │ │ │筛选│ │重编│ │分箱│ │条件│ ... │ │ │ │ └────┘ └────┘ └────┘ └────┘ │ │ │ └─────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────┐ │ │ │ 配置对话框(各功能独立) │ │ │ │ - 参数输入 │ │ │ │ - 实时预览 │ │ │ │ - 执行按钮 │ │ │ └─────────────────────────────────────────┘ │ └────────────────────┬────────────────────────────┘ │ HTTP POST ↓ ┌─────────────────────────────────────────────────┐ │ 后端 (Node.js + Fastify) │ │ ┌─────────────────────────────────────────┐ │ │ │ QuickActionController │ │ │ │ - 接收功能按钮请求 │ │ │ │ - 验证参数 │ │ │ │ - 调用QuickActionService │ │ │ └─────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────┐ │ │ │ ✅ QuickActionService (新) │ │ │ │ - executeFilter() 调用预写函数API │ │ │ │ - executeRecode() 调用预写函数API │ │ │ │ - executeBinning() 调用预写函数API │ │ │ └─────────────────────────────────────────┘ │ └────────────────────┬────────────────────────────┘ │ HTTP POST /api/operations/xxx ↓ ┌─────────────────────────────────────────────────┐ │ Python微服务 (FastAPI) │ │ ┌─────────────────────────────────────────┐ │ │ │ ✅ operations/ (预写函数模块) │ │ │ │ - filter.py (筛选) │ │ │ │ - recode.py (重编码) │ │ │ │ - binning.py (分箱) │ │ │ │ - conditional.py (条件生成,待开发) │ │ │ │ - missing.py (缺失值处理,待开发) │ │ │ │ 每个函数: │ │ │ │ ✓ 经过单元测试 │ │ │ │ ✓ 有完整类型注解 │ │ │ │ ✓ 有详细文档 │ │ │ └─────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────┐ │ │ │ ✅ API端点 (新) │ │ │ │ POST /api/operations/filter │ │ │ │ POST /api/operations/recode │ │ │ │ POST /api/operations/binning │ │ │ └─────────────────────────────────────────┘ │ └─────────────────────────────────────────────────┘ ``` **✅ 优势**: - ✅ **稳定性高**:预写函数经过单元测试,无字符串拼接风险 - ✅ **性能好**:直接调用函数,无代码解析开销 - ✅ **可维护**:代码集中在Python侧,便于优化 - ✅ **安全**:无代码注入风险 **❌ 已废弃**: - ~~QuickActionCodeGenerator.ts~~ (已删除) - ~~动态代码生成方案~~ (已弃用) ### 5.2 ✅ API设计(重构后) #### Node.js后端API(前端调用) ```typescript // 执行快速操作 POST /api/v1/dc/tool-c/quick-action Body: { sessionId: string, action: 'filter' | 'recode' | 'binning' | 'conditional' | ..., params: { // 各功能特定参数 } } Response: { success: boolean, data: { newDataPreview: Array, // 前50行预览 affectedRows: number, // 影响的行数 message: string, // 操作说明 executionTime: number, // Python执行时间(秒) output: string // Python打印输出 } } // 预览操作结果(不实际执行) POST /api/v1/dc/tool-c/quick-action/preview Body: { 同上 } Response: { success: boolean, data: { preview: Array, // 前10行预览 estimatedChange: string, // "将删除23行" / "将新增1列" originalRows: number, newRows: number } } ``` #### ✅ Python微服务API(后端调用,新增) **注意**:以下URL仅为示例,实际代码中使用环境变量 `EXTRACTION_SERVICE_URL` 配置。 ```python # 高级筛选(示例URL) POST http://localhost:8000/api/operations/filter Body: { "data": [{"年龄": 25, "性别": "男"}, ...], "conditions": [ {"column": "年龄", "operator": ">", "value": 30}, {"column": "性别", "operator": "=", "value": "男"} ], "logic": "and" # or "or" } Response: { "success": true, "result_data": [...], # 筛选后的数据 "output": "原始数据: 100 行\n筛选后: 30 行...", "execution_time": 0.023, "result_shape": [30, 5] } # 数值映射(重编码) POST http://localhost:8000/api/operations/recode Body: { "data": [{"性别": "男"}, {"性别": "女"}, ...], "column": "性别", "mapping": {"男": 1, "女": 2}, "create_new_column": true, "new_column_name": "性别_编码" } Response: { "success": true, "result_data": [...], "output": "映射完成: 96 个值成功映射\n映射成功率: 100.0%", "execution_time": 0.015, "result_shape": [96, 6] } # 生成分类变量(分箱) POST http://localhost:8000/api/operations/binning Body: { "data": [{"年龄": 25}, {"年龄": 35}, ...], "column": "年龄", "method": "custom", # or "equal_width", "equal_freq" "new_column_name": "年龄分组", "bins": [18, 60], # 自定义切点 "labels": ["青少年", "成年", "老年"] } Response: { "success": true, "result_data": [...], "output": "分箱结果分布:\n 青少年: 10 行 (10.4%)\n 成年: 70 行 (72.9%)...", "execution_time": 0.018, "result_shape": [96, 6] } ``` ### 5.3 ✅ 预写函数服务设计(重构后) #### Node.js后端服务 ```typescript // backend/src/modules/dc/tool-c/services/QuickActionService.ts export class QuickActionService { // 调用Python微服务的预写函数API async executeFilter(data: any[], params: FilterParams): Promise { return axios.post(`${PYTHON_SERVICE_URL}/api/operations/filter`, { data, conditions: params.conditions, logic: params.logic, }); } async executeRecode(data: any[], params: RecodeParams): Promise { return axios.post(`${PYTHON_SERVICE_URL}/api/operations/recode`, { data, column: params.column, mapping: params.mapping, create_new_column: params.createNewColumn, new_column_name: params.newColumnName, }); } async executeBinning(data: any[], params: BinningParams): Promise { return axios.post(`${PYTHON_SERVICE_URL}/api/operations/binning`, { data, column: params.column, method: params.method, new_column_name: params.newColumnName, bins: params.bins, labels: params.labels, num_bins: params.numBins, }); } } ``` #### Python预写函数 ```python # extraction_service/operations/filter.py def apply_filter(df: pd.DataFrame, conditions: List[Dict], logic: str) -> pd.DataFrame: """ 应用筛选条件(预写函数,经过充分测试) Args: df: 输入数据框 conditions: 筛选条件列表 logic: 'and' 或 'or' Returns: 筛选后的数据框 """ # 生成各个条件的mask masks = [] for cond in conditions: column = cond['column'] operator = cond['operator'] value = cond.get('value') if operator == '=': mask = df[column] == value elif operator == '>': mask = df[column] > value # ... 其他运算符 masks.append(mask) # 组合条件 if logic == 'and': final_mask = pd.concat(masks, axis=1).all(axis=1) else: final_mask = pd.concat(masks, axis=1).any(axis=1) return df[final_mask].copy() # extraction_service/main.py @app.post("/api/operations/filter") async def operation_filter(request: FilterRequest): """调用预写函数""" df = pd.DataFrame(request.data) result_df = apply_filter(df, request.conditions, request.logic) return JSONResponse(content={ "success": True, "result_data": result_df.to_dict('records'), "execution_time": execution_time, ... }) ``` **✅ 优势**: - 预写函数经过单元测试,稳定可靠 - 无字符串拼接,无代码注入风险 - 直接调用函数,性能优秀 - 代码集中管理,易于维护和优化 **❌ 已废弃**: - ~~QuickActionCodeGenerator.ts~~ (已删除,不再使用动态代码生成) ### 5.4 环境变量配置 **重要**:代码中使用环境变量配置Python微服务地址,**不使用硬编码**。 #### Node.js后端配置 在 `backend/.env` 中配置: ```bash # Python微服务地址(必需) EXTRACTION_SERVICE_URL=http://localhost:8000 # 生产环境示例 # EXTRACTION_SERVICE_URL=http://python-service:8000 # EXTRACTION_SERVICE_URL=https://api.yourdomain.com/python ``` #### 代码实现 ```typescript // backend/src/modules/dc/tool-c/services/QuickActionService.ts const PYTHON_SERVICE_URL = process.env.EXTRACTION_SERVICE_URL || 'http://localhost:8000'; // 调用时使用环境变量 await axios.post(`${PYTHON_SERVICE_URL}/api/operations/filter`, {...}); ``` **✅ 优势**: - 开发环境:使用 `localhost:8000` - 生产环境:使用内网地址或域名 - 容器化部署:使用服务名(如 `http://python-service:8000`) - 符合云原生开发规范 --- ## 6. 详细设计 ### 6.1 高级筛选器 #### UI设计 ``` ┌─────────────────────────────────────────┐ │ 高级筛选 │ ├─────────────────────────────────────────┤ │ ┌─────────────────────────────────────┐│ │ │ [列名 ▼] [条件 ▼] [值_________] ││ │ └─────────────────────────────────────┘│ │ [且 ▼] │ │ ┌─────────────────────────────────────┐│ │ │ [列名 ▼] [条件 ▼] [值_________] ││ │ └─────────────────────────────────────┘│ │ [+ 添加条件] │ │ │ │ 预览:将保留 87 行(共100行) │ │ │ │ [取消] [预览] [应用] │ └─────────────────────────────────────────┘ ``` #### 条件运算符 - 数值列:`=`, `≠`, `>`, `<`, `≥`, `≤` - 文本列:`等于`, `不等于`, `包含`, `不包含`, `以...开头`, `以...结尾` - 通用:`为空`, `不为空` #### 生成代码示例 ```python # 单条件 df = df[df['年龄'] >= 18] # 多条件 AND df = df[(df['年龄'] >= 18) & (df['性别'] == '男')] # 多条件 OR df = df[(df['年龄'] >= 60) | (df['BMI'] >= 28)] # 包含 df = df[df['诊断'].str.contains('糖尿病', na=False)] # 不为空 df = df[df['BMI'].notna()] ``` --- ### 6.2 数值映射(重编码) #### UI设计 ``` ┌─────────────────────────────────────┐ │ 变量重编码 │ ├─────────────────────────────────────┤ │ 选择列:[研究中心 ▼] │ │ │ │ 自动检测到 3 个唯一值: │ │ ┌─────────────────┬─────────────┐ │ │ │ 原值 │ 新值 │ │ │ ├─────────────────┼─────────────┤ │ │ │ 黑龙江中医药... │ [1______] │ │ │ │ 山东中医药... │ [2______] │ │ │ │ 广州中医药... │ [3______] │ │ │ └─────────────────┴─────────────┘ │ │ │ │ ☑️ 创建新列(推荐) │ │ 新列名:[研究中心_编码_______] │ │ │ │ [取消] [预览] [执行] │ └─────────────────────────────────────┘ ``` #### 生成代码示例 ```python # 创建新列 mapping = { '黑龙江中医药大学附属第二医院': 1, '山东中医药大学附属医院': 2, '广州中医药大学附属第一医院': 3 } df['研究中心_编码'] = df['研究中心'].map(mapping) # 或覆盖原列 df['研究中心'] = df['研究中心'].map(mapping) ``` --- ### 6.3 生成分类变量(分箱) #### UI设计 ``` ┌─────────────────────────────────────┐ │ 连续变量分箱 │ ├─────────────────────────────────────┤ │ 选择数值列:[督脉针刺持续时间 ▼] │ │ │ │ 分箱方式: │ │ ● 自定义切点 │ │ 切点:[10] [+] │ │ 标签: │ │ ≥10: [暴露=1_____] │ │ <10: [非暴露=0___] │ │ │ │ ○ 多段切点 │ │ 切点:[0] [14] [30] [999] │ │ 标签:[低=0][中=1][高=2] │ │ │ │ 新列名:[住院患者暴露分组_____] │ │ │ │ [取消] [预览分布] [执行] │ └─────────────────────────────────────┘ ``` #### 生成代码示例 ```python # 二分类(单切点) df['住院患者暴露分组'] = (df['督脉针刺持续时间'] >= 10).astype(int) # 多分类(多切点) df['暴露强度分组'] = pd.cut( df['督脉针刺持续时间'], bins=[0, 14, 30, 999], labels=[0, 1, 2], right=False ) ``` --- ### 6.4 条件生成列 ⭐核心功能 #### UI设计 ``` ┌─────────────────────────────────────────┐ │ 条件生成新列 │ ├─────────────────────────────────────────┤ │ 新列名:[住院暴露出院暴露情况分组____] │ │ │ │ 规则(按顺序匹配): │ │ ┌───────────────────────────────────┐ │ │ │ 规则1 │ │ │ │ IF [住院患者暴露分组▼] [=▼] [1] │ │ │ │ [且▼] │ │ │ │ IF [督脉针刺持续时间▼] [>=▼][14] │ │ │ │ THEN 值为:[住院暴露出院暴露____] │ │ │ │ [删除规则]│ │ │ └───────────────────────────────────┘ │ │ ┌───────────────────────────────────┐ │ │ │ 规则2 │ │ │ │ IF [住院患者暴露分组▼] [=▼] [1] │ │ │ │ [且▼] │ │ │ │ IF [督脉针刺持续时间▼] [<▼] [14] │ │ │ │ THEN 值为:[住院暴露出院非暴露__] │ │ │ │ [删除规则]│ │ │ └───────────────────────────────────┘ │ │ [+ 添加规则] │ │ │ │ 其他情况(ELSE): │ │ ● 留空(None) │ │ ○ 固定值:[_______] │ │ ○ 使用默认值:[0______] │ │ │ │ 预览:将生成新列,预计87行有值 │ │ │ │ [取消] [预览前10行] [执行] │ └─────────────────────────────────────────┘ ``` #### 技术实现 **前端数据结构**: ```typescript interface ConditionalRule { conditions: Array<{ column: string, operator: '=' | '!=' | '>' | '<' | '>=' | '<=', value: string | number }>, logic: 'and' | 'or', result: string | number } interface ConditionalParams { newColumnName: string, rules: ConditionalRule[], elseValue: null | string | number } ``` **生成代码示例**: ```python def classify_exposure(row): # 规则1 if row['住院患者暴露分组'] == 1 and row['督脉针刺持续时间'] >= 14: return '住院暴露出院暴露' # 规则2 elif row['住院患者暴露分组'] == 1 and row['督脉针刺持续时间'] < 14: return '住院暴露出院非暴露' # ELSE else: return None df['住院暴露出院暴露情况分组'] = df.apply(classify_exposure, axis=1) ``` --- ### 6.5 长表→宽表(Pivot) #### UI设计 ``` ┌─────────────────────────────────────┐ │ 长表转宽表(Pivot) │ ├─────────────────────────────────────┤ │ 索引列(唯一标识): │ │ [Record ID ▼] │ │ │ │ 透视列(变成列名): │ │ [Event Name ▼] │ │ 检测到的值: │ │ • 筛选及基线 │ │ • 随访(2周) │ │ • 随访(1个月) │ │ │ │ 值列(要转置的数据): │ │ ☑️ FMA总得分 │ │ ☑️ FMA分级(1-5) │ │ ☑️ ADL总分 │ │ ☑️ NLR │ │ ☑️ PLR │ │ [ ] ...(选择其他列) │ │ │ │ 重复值处理: │ │ ● 取第一个 ○ 取最后一个 │ │ ○ 求平均值 ○ 求和 │ │ │ │ [取消] [预览结构] [执行] │ └─────────────────────────────────────┘ ``` #### 生成代码示例 ```python # Pivot转换 df_pivot = df.pivot_table( index='Record ID', columns='Event Name', values=['FMA总得分', 'FMA分级(1-5)', 'ADL总分', 'NLR', 'PLR'], aggfunc='first' ) # 展平多级列名 df_pivot.columns = ['_'.join(col).strip() for col in df_pivot.columns.values] df_pivot = df_pivot.reset_index() # 示例:FMA总得分_筛选及基线, FMA总得分_随访(2周) ``` --- ### 6.6 多重插补(MICE) #### UI设计 ``` ┌─────────────────────────────────────┐ │ 多重插补(MICE) │ ├─────────────────────────────────────┤ │ ⚠️ 高级统计功能,需谨慎使用 │ │ │ │ 选择需要插补的列: │ │ ☑️ 年龄 │ │ ☑️ BMI │ │ ☑️ 血糖 │ │ [ ] 血压 │ │ [ ] ... │ │ │ │ 参数设置: │ │ 迭代次数:[10____](推荐5-20) │ │ 随机种子:[42____](可重复结果) │ │ │ │ 预计插补:32个缺失值 │ │ │ │ ⚠️ 注意: │ │ • MICE假设数据MAR(随机缺失) │ │ • 插补时间较长(大数据集>1分钟) │ │ • 建议先备份原数据 │ │ │ │ [取消] [执行] │ └─────────────────────────────────────┘ ``` #### 技术实现 **依赖库**:需在Python微服务中安装 `scikit-learn` ```python from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer # 选择需要插补的列 cols_to_impute = ['年龄', 'BMI', '血糖'] df_subset = df[cols_to_impute] # MICE插补 imputer = IterativeImputer( max_iter=10, random_state=42, verbose=0 ) df[cols_to_impute] = imputer.fit_transform(df_subset) print(f'插补完成,剩余缺失值: {df[cols_to_impute].isna().sum().sum()}') ``` --- ## 7. 验收标准 ### 7.1 功能验收 每个功能按钮需通过以下测试: #### 基础功能测试 | 测试项 | 验收标准 | |-------|---------| | UI显示 | 按钮、对话框正确渲染,无布局错误 | | 参数验证 | 错误输入有友好提示 | | 预览功能 | 预览结果准确,性能<2秒 | | 执行功能 | 代码正确执行,结果符合预期 | | 错误处理 | 异常有明确提示,不崩溃 | #### 数据准确性测试 | 测试项 | 验收标准 | |-------|---------| | 小数据集 | <1000行,结果100%准确 | | 中数据集 | 1000-10000行,性能<5秒 | | 大数据集 | 10000-50000行,性能<30秒 | | 边界情况 | 全空列、全0列、单行等正确处理 | #### 用户体验测试 | 测试项 | 验收标准 | |-------|---------| | 学习成本 | 新用户5分钟内学会使用 | | 操作效率 | 比AI对话快3-5倍 | | 错误恢复 | 支持撤销或提供"创建副本"选项 | ### 7.2 性能基准 | 操作 | 数据量 | 目标性能 | |------|-------|---------| | 高级筛选 | 10万行 | <2秒 | | 数值映射 | 10万行 | <3秒 | | 分箱 | 10万行 | <3秒 | | 条件生成列 | 10万行 | <5秒 | | Pivot转换 | 5000行 | <10秒 | | MICE插补 | 5000行 | <60秒 | ### 7.3 代码质量标准 - ✅ 代码覆盖率 >80% - ✅ ESLint/TSLint 0错误 - ✅ 所有API有完整的TypeScript类型定义 - ✅ 关键函数有JSDoc注释 - ✅ 用户操作有日志记录 --- ## 8. 风险评估 ### 8.1 技术风险 | 风险 | 影响 | 概率 | 应对措施 | |------|------|------|---------| | Python库依赖问题 | 高 | 中 | 提前验证库兼容性 | | 大数据集性能 | 中 | 高 | 分批处理+进度条 | | 代码生成错误 | 高 | 低 | 严格单元测试 | | 浏览器兼容性 | 低 | 低 | 只支持现代浏览器 | ### 8.2 用户体验风险 | 风险 | 影响 | 概率 | 应对措施 | |------|------|------|---------| | 功能过于复杂 | 中 | 中 | 提供视频教程 | | 与AI功能冲突 | 低 | 低 | 明确使用场景 | | 期望过高 | 中 | 中 | 明确功能边界 | --- ## 9. 后续规划 ### Phase 5:智能化增强(2-3个月后) 1. **操作推荐**:根据数据特征推荐合适的操作 2. **自动诊断**:检测数据质量问题(缺失、异常、重复) 3. **批量操作**:一次性应用多个操作 4. **操作模板**:保存常用操作序列 ### Phase 6:协作增强(3-6个月后) 1. **操作历史**:查看、回退、分享操作历史 2. **团队模板**:团队共享清洗模板 3. **数据版本**:支持数据快照和版本管理 --- ## 10. 附录 ### 10.1 参考资料 - SPSS数据清洗功能 - Excel数据透视表 - Python Pandas文档 - Ant Design组件库 ### 10.2 术语表 | 术语 | 解释 | |------|------| | 重编码 | 将一列的值映射为另一组值 | | 分箱 | 将连续数值转为离散分类 | | Pivot | 长表转宽表的数据重塑操作 | | MICE | 多重插补法,处理缺失值的统计方法 | | MAR | Missing At Random,随机缺失 | ### 10.3 更新日志 | 版本 | 日期 | 变更内容 | |------|------|---------| | V1.0 | 2025-12-08 | 初版,规划Phase 1-4功能 | | V1.1 | 2025-12-08 | 架构重构:改为预写Python函数 | | V1.2 | 2025-12-08 | Phase 1-2完成:7个核心功能上线 | | V1.3 | 2025-12-10 | NA处理优化:4个功能支持空值处理;Pivot优化:保留未选列+原始列顺序;计算列方案B实施:安全列名映射;UX优化:列头tooltip+预览提示可关闭+滚动条优化 | | V1.4 | 2025-12-10 | 缺失值填补功能开发:6种简单填补(均值/中位数/众数/固定值/前向/后向)+MICE多重插补;自动精度检测;分类列识别;功能按钮调整(删除"去重"和"多重插补","删除缺失值"改为"缺失值处理");状态:开发完成,MICE的DataFrame shape问题待调试 | | V1.5 | 2025-12-10 | **UX优化重大改进**:①删除"前50行预览"提示条;②添加行号列(固定左侧,灰色背景);③列头筛选功能(Excel风格,Community版本,中文本地化,显示值计数);④全量数据加载与返回(不再限制50行,筛选精确);⑤**滚动条终极修复**(修改MainLayout为固定高度,整个页面无滚动条,只有表格内部滚动);⑥计算列特殊字符修复(全角字符自动转换+列别名机制);状态:**Tool C整体完成度98%,用户体验显著提升** ✅ | --- **文档结束**