Major features: 1. Missing value imputation (6 simple methods + MICE): - Mean/Median/Mode/Constant imputation - Forward fill (ffill) and Backward fill (bfill) for time series - MICE multivariate imputation (in progress, shape issue to fix) 2. Auto precision detection: - Automatically match decimal places of original data - Prevent false precision (e.g. 13.57 instead of 13.566716417910449) 3. Categorical variable detection: - Auto-detect and skip categorical columns in MICE - Show warnings for unsuitable columns - Suggest mode imputation for categorical data 4. UI improvements: - Rename button: "Delete Missing" to "Missing Value Handling" - Remove standalone "Dedup" and "MICE" buttons - 3-tab dialog: Delete / Fill / Advanced Fill - Display column statistics and recommended methods - Extended warning messages (8 seconds for skipped columns) 5. Bug fixes: - Fix sessionService.updateSessionData -> saveProcessedData - Fix OperationResult interface (add message and stats) - Fix Toolbar button labels and removal Modified files: Python: operations/fillna.py (new, 556 lines), main.py (3 new endpoints) Backend: QuickActionService.ts, QuickActionController.ts, routes/index.ts Frontend: MissingValueDialog.tsx (new, 437 lines), Toolbar.tsx, index.tsx Tests: test_fillna_operations.py (774 lines), test scripts and docs Docs: 5 documentation files updated Known issues: - MICE imputation has DataFrame shape mismatch issue (under debugging) - Workaround: Use 6 simple imputation methods first Status: Development complete, MICE debugging in progress Lines added: ~2000 lines across 3 tiers
737 lines
28 KiB
Markdown
737 lines
28 KiB
Markdown
# 工具C - 缺失值处理功能开发计划
|
||
|
||
## 📋 概述
|
||
|
||
**目标**:将现有的"删除缺失值"功能升级为综合的"缺失值处理"功能,包括删除、填补、高级填补三种策略。
|
||
|
||
**设计方案**:方案B - 合并对话框 + Tab切换
|
||
|
||
**核心原则**:
|
||
- ✅ **填补操作创建新列**(保留原始数据,便于对比)
|
||
- ✅ **新列紧邻原列**(方便用户查看和比较)
|
||
- ✅ **MICE功能必须实现**(医学研究核心需求)
|
||
- ✅ **无需撤销功能**(原始数据未被修改)
|
||
|
||
---
|
||
|
||
## 🎯 功能需求
|
||
|
||
### Phase 1:必备功能(本次开发)
|
||
|
||
#### Tab 1:删除缺失值 ✅ 已有
|
||
- 保留现有功能
|
||
- 删除包含缺失值的行
|
||
- 删除缺失率过高的列
|
||
|
||
#### Tab 2:填补缺失值 ⭐ 新增
|
||
1. **均值填补**(Mean Imputation)
|
||
- 适用于:数值型变量,正态分布
|
||
- 实现:创建新列,填充均值
|
||
|
||
2. **中位数填补**(Median Imputation)
|
||
- 适用于:数值型变量,偏态分布
|
||
- 实现:创建新列,填充中位数
|
||
|
||
3. **众数填补**(Mode Imputation)
|
||
- 适用于:分类变量、离散型数值
|
||
- 实现:创建新列,填充众数
|
||
|
||
4. **固定值填补**(Constant Imputation)
|
||
- 适用于:任何类型,用户指定值
|
||
- 实现:创建新列,填充指定值
|
||
|
||
5. **前向填充**(Forward Fill)
|
||
- 适用于:时间序列数据、有顺序的观察数据
|
||
- 实现:`df[column].fillna(method='ffill')`,用前一个非缺失值填充
|
||
- 示例:[10, NaN, NaN, 20] → [10, 10, 10, 20]
|
||
|
||
6. **后向填充**(Backward Fill)
|
||
- 适用于:时间序列数据、有顺序的观察数据
|
||
- 实现:`df[column].fillna(method='bfill')`,用后一个非缺失值填充
|
||
- 示例:[10, NaN, NaN, 20] → [10, 20, 20, 20]
|
||
|
||
**注意**:所有填补方法都会创建新列(如`体重_填补`),新列紧邻原列,便于对比验证。
|
||
|
||
#### Tab 3:高级填补 ⭐ 新增
|
||
1. **MICE多重插补**(Multivariate Imputation by Chained Equations)
|
||
- 适用于:缺失率5%-30%,需要考虑变量间关系
|
||
- 实现:使用 `sklearn.impute.IterativeImputer`
|
||
|
||
### Phase 2:未来扩展(本次不开发)
|
||
- 分组填补(Grouped Imputation)
|
||
- 线性插值(Linear Interpolation)
|
||
- KNN填补(KNN Imputation)
|
||
- 组合填补(根据条件使用不同填补方法)
|
||
|
||
---
|
||
|
||
## 🎨 UI设计
|
||
|
||
### 1. 按钮重命名
|
||
**原**:`[删除缺失值]`
|
||
**新**:`[缺失值处理]`
|
||
|
||
### 2. 对话框结构
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────┐
|
||
│ 缺失值处理 [X] │
|
||
├───────────────────────────────────────────────────────┤
|
||
│ ┌────────┬────────┬──────────┐ │
|
||
│ │ 删除 │ 填补 │ 高级填补 │ ← Ant Design Tabs │
|
||
│ └────────┴────────┴──────────┘ │
|
||
├───────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ 【Tab内容区域】 │
|
||
│ │
|
||
│ │
|
||
│ [取消] [执行处理] │
|
||
└───────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3. Tab 2(填补)详细设计
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────┐
|
||
│ 【Tab 2: 填补缺失值】 │
|
||
│ │
|
||
│ 原始列:[体重(kg)▼] │
|
||
│ ⚠️ 仅支持单列填补 │
|
||
│ │
|
||
│ 新列名:[体重_填补 ] ← 用户可修改 │
|
||
│ 💡 新列将创建在原列旁边,便于对比 │
|
||
│ │
|
||
│ 📊 缺失值统计: │
|
||
│ ┌──────────────────────────────────────────────┐ │
|
||
│ │ • 当前缺失:125个(15.6%) │ │
|
||
│ │ • 有效值:675个(84.4%) │ │
|
||
│ │ • 数据类型:数值型 │ │
|
||
│ │ • 有效值范围:45.2 - 98.5 kg │ │
|
||
│ │ • 有效值均值:70.3 kg │ │
|
||
│ │ • 有效值中位数:68.5 kg │ │
|
||
│ │ • 推荐方法:中位数填补(数据偏态)⭐ │ │
|
||
│ └──────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 填补方法: │
|
||
│ ⚪ 均值填补(适合正态分布的数值变量) │
|
||
│ ⚪ 中位数填补(适合偏态分布的数值变量)⭐ │
|
||
│ ⚪ 众数填补(适合分类变量或离散数值) │
|
||
│ ⚪ 固定值填补:[_______] ← 用户输入 │
|
||
│ ⚪ 前向填充(用前一个值填充,适合时间序列) │
|
||
│ ⚪ 后向填充(用后一个值填充,适合时间序列) │
|
||
│ │
|
||
│ 📈 填补预览: │
|
||
│ ┌──────────────────────────────────────────────┐ │
|
||
│ │ • 填补值:68.5 kg │ │
|
||
│ │ • 填补后均值:70.2 kg(原75.3 kg) │ │
|
||
│ │ • 填补后标准差:12.5 kg(原10.8 kg) │ │
|
||
│ │ • 将创建新列:"体重_填补" │ │
|
||
│ │ • 原列"体重(kg)"保持不变 ✅ │ │
|
||
│ └──────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ✅ 优势:原始数据保留,可随时对比验证 │
|
||
│ │
|
||
│ [取消] [执行填补] │
|
||
└───────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4. Tab 3(高级填补)详细设计
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────┐
|
||
│ 【Tab 3: 高级填补 - MICE多重插补】⭐ 必须实现 │
|
||
│ │
|
||
│ ⭐ MICE多重插补 │
|
||
│ (Multivariate Imputation by Chained Equations) │
|
||
│ │
|
||
│ 选择要填补的列(可多选): │
|
||
│ ┌──────────────────────────────────────────────┐ │
|
||
│ │ ☑ 体重(kg) 缺失:125(15.6%) │ │
|
||
│ │ ☑ 收缩压(mmHg) 缺失:82(10.3%) │ │
|
||
│ │ ☐ BMI 缺失:3(0.4%) │ │
|
||
│ │ ☐ 舒张压(mmHg) 缺失:0(0%) │ │
|
||
│ └──────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 新列命名规则: │
|
||
│ ☑ 自动命名:原列名 + "_MICE" │
|
||
│ 示例:体重(kg) → 体重(kg)_MICE │
|
||
│ 收缩压(mmHg) → 收缩压(mmHg)_MICE │
|
||
│ │
|
||
│ 参数设置: │
|
||
│ 迭代次数:[10▼] (默认10次,范围5-50) │
|
||
│ 随机种子:[42 ] (确保结果可重复) │
|
||
│ │
|
||
│ 📊 MICE说明: │
|
||
│ ┌──────────────────────────────────────────────┐ │
|
||
│ │ MICE会根据其他变量的值来预测缺失值。 │ │
|
||
│ │ │ │
|
||
│ │ ✅ 适用场景: │ │
|
||
│ │ • 缺失率5%-30% │ │
|
||
│ │ • 需要考虑变量间的相关性 │ │
|
||
│ │ • 多个变量同时有缺失 │ │
|
||
│ │ • 医学研究高质量填补的首选方法 ⭐ │ │
|
||
│ │ │ │
|
||
│ │ ⚠️ 注意: │ │
|
||
│ │ • 计算时间较长(10万行约1分钟) │ │
|
||
│ │ • 需要足够的有效样本(建议>50%有效) │ │
|
||
│ │ • 新列将创建在各原列旁边,便于对比 │ │
|
||
│ └──────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 💡 新列位置:每个新列紧邻其原列,便于逐列验证 │
|
||
│ │
|
||
│ [取消] [执行MICE填补] │
|
||
└───────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ 技术实现方案
|
||
|
||
### 1. Python端(extraction_service)
|
||
|
||
#### 新增文件:`operations/fillna.py`
|
||
|
||
```python
|
||
"""
|
||
缺失值填补 - 预写函数
|
||
支持均值、中位数、众数、固定值、MICE填补
|
||
"""
|
||
|
||
import pandas as pd
|
||
import numpy as np
|
||
from typing import Literal, Optional, List, Union, Any
|
||
from sklearn.impute import IterativeImputer
|
||
|
||
|
||
def fillna_simple(
|
||
df: pd.DataFrame,
|
||
column: str,
|
||
new_column_name: str,
|
||
method: Literal['mean', 'median', 'mode', 'constant', 'ffill', 'bfill'],
|
||
fill_value: Any = None
|
||
) -> dict:
|
||
"""
|
||
简单填补缺失值(创建新列)
|
||
|
||
Args:
|
||
df: 输入数据框
|
||
column: 原始列名
|
||
new_column_name: 新列名(如"体重_填补")
|
||
method: 填补方法
|
||
- 'mean': 均值填补
|
||
- 'median': 中位数填补
|
||
- 'mode': 众数填补
|
||
- 'constant': 固定值填补
|
||
- 'ffill': 前向填充(用前一个非缺失值)
|
||
- 'bfill': 后向填充(用后一个非缺失值)
|
||
fill_value: 固定值(method='constant'时必填)
|
||
|
||
Returns:
|
||
{
|
||
'df': 包含新列的数据框(新列紧邻原列),
|
||
'stats': {
|
||
'original_column': 原列名,
|
||
'new_column': 新列名,
|
||
'missing_before': 缺失数量,
|
||
'fill_value': 填补的值,
|
||
'mean_after': 填补后均值,
|
||
'std_after': 填补后标准差
|
||
}
|
||
}
|
||
|
||
实现细节:
|
||
1. 复制原列数据
|
||
2. 执行填补
|
||
3. 使用 df.insert() 将新列插入到原列旁边
|
||
4. 返回包含新列的完整数据框
|
||
"""
|
||
|
||
def get_column_missing_stats(
|
||
df: pd.DataFrame,
|
||
column: str
|
||
) -> dict:
|
||
"""
|
||
获取列的缺失值统计信息
|
||
|
||
Returns:
|
||
{
|
||
'missing_count': 缺失数量,
|
||
'missing_rate': 缺失率,
|
||
'valid_count': 有效值数量,
|
||
'data_type': 数据类型,
|
||
'value_range': [min, max], # 仅数值型
|
||
'mean': 均值, # 仅数值型
|
||
'median': 中位数, # 仅数值型
|
||
'mode': 众数,
|
||
'recommended_method': 推荐的填补方法
|
||
}
|
||
"""
|
||
|
||
def fillna_mice(
|
||
df: pd.DataFrame,
|
||
columns: List[str],
|
||
n_iterations: int = 10,
|
||
random_state: int = 42
|
||
) -> dict:
|
||
"""
|
||
MICE多重插补(创建新列)⭐ 必须实现
|
||
|
||
Args:
|
||
df: 输入数据框
|
||
columns: 要填补的列名列表(如["体重(kg)", "收缩压(mmHg)"])
|
||
n_iterations: 迭代次数(默认10,范围5-50)
|
||
random_state: 随机种子(默认42,确保结果可重复)
|
||
|
||
Returns:
|
||
{
|
||
'df': 包含所有新列的数据框(每个新列紧邻其原列),
|
||
'stats': {
|
||
column: {
|
||
'original_column': 原列名,
|
||
'new_column': 新列名(原名_MICE),
|
||
'missing_before': 缺失数量,
|
||
'filled_count': 填补数量,
|
||
'mean_before': 填补前均值,
|
||
'mean_after': 填补后均值
|
||
}
|
||
}
|
||
}
|
||
|
||
实现细节:
|
||
1. 对所选列执行MICE填补
|
||
2. 为每列创建新列(命名:原列名_MICE)
|
||
3. 使用 df.insert() 将每个新列插入到其原列旁边
|
||
4. 返回包含所有新列的完整数据框
|
||
|
||
示例:
|
||
原列:体重(kg)、收缩压(mmHg)
|
||
新列:体重(kg)_MICE、收缩压(mmHg)_MICE
|
||
结果顺序:体重(kg)、体重(kg)_MICE、收缩压(mmHg)、收缩压(mmHg)_MICE、...
|
||
"""
|
||
```
|
||
|
||
#### 修改文件:`main.py`
|
||
|
||
```python
|
||
# 新增API端点
|
||
|
||
@app.post("/fillna-simple")
|
||
async def operation_fillna_simple(request: FillnaSimpleRequest):
|
||
"""简单填补缺失值"""
|
||
|
||
@app.post("/fillna-stats")
|
||
async def get_fillna_stats(request: FillnaStatsRequest):
|
||
"""获取列的缺失值统计"""
|
||
|
||
@app.post("/fillna-mice")
|
||
async def operation_fillna_mice(request: FillnaMiceRequest):
|
||
"""MICE多重插补"""
|
||
```
|
||
|
||
### 2. Node.js后端(backend)
|
||
|
||
#### 修改文件:`services/QuickActionService.ts`
|
||
|
||
```typescript
|
||
// 新增方法
|
||
|
||
async executeFillnaSimple(params: {
|
||
sessionId: string;
|
||
column: string;
|
||
method: 'mean' | 'median' | 'mode' | 'constant' | 'ffill' | 'bfill';
|
||
fillValue?: any;
|
||
}): Promise<any>
|
||
|
||
async getFillnaStats(params: {
|
||
sessionId: string;
|
||
column: string;
|
||
}): Promise<any>
|
||
|
||
async executeFillnaMice(params: {
|
||
sessionId: string;
|
||
columns: string[];
|
||
nIterations: number;
|
||
}): Promise<any>
|
||
```
|
||
|
||
#### 修改文件:`controllers/QuickActionController.ts`
|
||
|
||
```typescript
|
||
// 新增处理方法
|
||
|
||
async handleFillnaSimple(request, reply)
|
||
async getFillnaStats(request, reply)
|
||
async handleFillnaMice(request, reply)
|
||
```
|
||
|
||
### 3. 前端(frontend-v2)
|
||
|
||
#### 重命名文件
|
||
- `DropnaDialog.tsx` → `MissingValueDialog.tsx`
|
||
|
||
#### 修改文件:`MissingValueDialog.tsx`
|
||
|
||
```typescript
|
||
interface MissingValueDialogProps {
|
||
open: boolean;
|
||
onClose: () => void;
|
||
sessionId: string;
|
||
columns: Array<{ id: string; name: string; type?: string }>;
|
||
onSuccess: () => void;
|
||
}
|
||
|
||
// 新增状态
|
||
const [activeTab, setActiveTab] = useState<'delete' | 'fill' | 'mice'>('fill');
|
||
const [selectedColumn, setSelectedColumn] = useState<string>('');
|
||
const [fillMethod, setFillMethod] = useState<'mean' | 'median' | 'mode' | 'constant' | 'ffill' | 'bfill'>('median');
|
||
const [fillValue, setFillValue] = useState<any>(null);
|
||
const [columnStats, setColumnStats] = useState<any>(null);
|
||
|
||
// Tab 1: 删除(保留原有逻辑)
|
||
// Tab 2: 填补(新增)
|
||
// Tab 3: MICE(新增)
|
||
```
|
||
|
||
#### 修改文件:`index.tsx`
|
||
|
||
```typescript
|
||
// 更新按钮组
|
||
const actionButtons = [
|
||
// ...
|
||
{
|
||
key: 'missing',
|
||
icon: <DeleteOutlined />,
|
||
label: '缺失值处理', // ← 重命名
|
||
onClick: () => setMissingValueDialogOpen(true),
|
||
},
|
||
// ...
|
||
];
|
||
```
|
||
|
||
---
|
||
|
||
## 📂 文件修改清单
|
||
|
||
### 新增文件
|
||
1. `extraction_service/operations/fillna.py` - 填补功能实现
|
||
2. `docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理功能开发计划.md` - 本文档
|
||
|
||
### 修改文件
|
||
|
||
#### Python端
|
||
1. `extraction_service/main.py`
|
||
- 新增 `/fillna-simple` 端点
|
||
- 新增 `/fillna-stats` 端点
|
||
- 新增 `/fillna-mice` 端点
|
||
|
||
#### Node.js后端
|
||
2. `backend/src/modules/dc/tool-c/services/QuickActionService.ts`
|
||
- 新增 `executeFillnaSimple` 方法
|
||
- 新增 `getFillnaStats` 方法
|
||
- 新增 `executeFillnaMice` 方法
|
||
|
||
3. `backend/src/modules/dc/tool-c/controllers/QuickActionController.ts`
|
||
- 新增 `handleFillnaSimple` 处理方法
|
||
- 新增 `getFillnaStats` 处理方法
|
||
- 新增 `handleFillnaMice` 处理方法
|
||
|
||
#### 前端
|
||
4. `frontend-v2/src/modules/dc/pages/tool-c/components/DropnaDialog.tsx`
|
||
- **重命名为** `MissingValueDialog.tsx`
|
||
- 新增 Tabs 组件(删除/填补/高级填补)
|
||
- Tab 1: 保留原有删除功能
|
||
- Tab 2: 新增简单填补功能(均值/中位数/众数/固定值)
|
||
- Tab 3: 新增MICE填补功能
|
||
|
||
5. `frontend-v2/src/modules/dc/pages/tool-c/index.tsx`
|
||
- 更新按钮标签:`删除缺失值` → `缺失值处理`
|
||
- 更新 Dialog 组件引用
|
||
|
||
6. `frontend-v2/src/modules/dc/api/index.ts`
|
||
- 新增 `fillnaSimple` API
|
||
- 新增 `getFillnaStats` API
|
||
- 新增 `fillnaMice` API
|
||
|
||
---
|
||
|
||
## 🔄 开发步骤
|
||
|
||
### Step 1: Python端基础功能(30min)
|
||
1. 创建 `fillna.py`
|
||
2. 实现 `fillna_simple` 函数
|
||
3. 实现 `get_column_missing_stats` 函数
|
||
4. 在 `main.py` 添加对应端点
|
||
5. 测试:使用Postman或curl测试API
|
||
|
||
### Step 2: Python端高级功能(30min)
|
||
1. 实现 `fillna_mice` 函数
|
||
2. 在 `main.py` 添加对应端点
|
||
3. 测试:使用Postman测试MICE功能
|
||
|
||
### Step 3: Node.js后端(20min)
|
||
1. 修改 `QuickActionService.ts`
|
||
2. 修改 `QuickActionController.ts`
|
||
3. 测试:确保API转发正常
|
||
|
||
### Step 4: 前端UI重构(40min)
|
||
1. 重命名 `DropnaDialog.tsx` → `MissingValueDialog.tsx`
|
||
2. 实现Tabs结构
|
||
3. Tab 1: 迁移原有删除功能
|
||
4. Tab 2: 实现简单填补UI
|
||
5. Tab 3: 实现MICE填补UI
|
||
6. 更新 `index.tsx` 中的引用和按钮标签
|
||
|
||
### Step 5: 前端API集成(20min)
|
||
1. 在 `api/index.ts` 添加新API
|
||
2. 集成到 `MissingValueDialog.tsx`
|
||
3. 实现实时统计获取
|
||
4. 实现填补预览
|
||
|
||
### Step 6: 端到端测试(30min)
|
||
1. 测试均值填补
|
||
2. 测试中位数填补
|
||
3. 测试众数填补
|
||
4. 测试固定值填补
|
||
5. 测试MICE填补
|
||
6. 测试删除功能(确保未破坏原有功能)
|
||
|
||
### Step 7: 优化和文档(20min)
|
||
1. 添加错误处理
|
||
2. 优化加载状态
|
||
3. 更新用户提示
|
||
4. 记录开发总结
|
||
|
||
**总计:约3小时**
|
||
|
||
---
|
||
|
||
## 🧪 测试计划
|
||
|
||
### 功能测试用例
|
||
|
||
#### 测试数据准备
|
||
```
|
||
- 数值列(正态分布):年龄(缺失15%)
|
||
- 数值列(偏态分布):体重(缺失20%)
|
||
- 分类列:婚姻状况(缺失10%)
|
||
- 多列缺失:收缩压(15%)+ 舒张压(12%)
|
||
- 时间序列列:随访血压(有顺序,缺失18%)- 用于测试前/后向填充
|
||
```
|
||
|
||
#### 测试用例
|
||
|
||
| 编号 | 功能 | 测试场景 | 预期结果 |
|
||
|------|------|----------|----------|
|
||
| TC-1 | 均值填补 | 对"年龄"列使用均值填补,新列名"年龄_填补" | 创建新列,缺失值被均值填充,原列不变 ✅ |
|
||
| TC-2 | 中位数填补 | 对"体重"列使用中位数填补 | 创建新列,缺失值被中位数填充 ✅ |
|
||
| TC-3 | 众数填补 | 对"婚姻状况"列使用众数填补 | 创建新列,缺失值被众数填充 ✅ |
|
||
| TC-4 | 固定值填补(数值) | 对"年龄"列填充固定值"0" | 创建新列,所有缺失值变为0 ✅ |
|
||
| TC-5 | 固定值填补(文本) | 对"婚姻状况"列填充"未知" | 创建新列,所有缺失值变为"未知" ✅ |
|
||
| TC-6 | MICE填补 | 选择"收缩压"+"舒张压",执行MICE | 创建2个新列(_MICE后缀),缺失值被预测 ✅ |
|
||
| TC-7 | 新列位置验证 ⭐ | 对"列A"填补,查看新列位置 | 新列"列A_填补"紧邻原列"列A"右侧 ✅ |
|
||
| TC-8 | MICE新列位置 ⭐ | 对"列A"+"列C"执行MICE | 列A_MICE在列A旁,列C_MICE在列C旁 ✅ |
|
||
| TC-9 | 统计信息准确性 | 选择任意列,查看统计信息 | 显示正确的缺失数、均值、中位数等 |
|
||
| TC-10 | 删除功能保留 | Tab 1删除缺失行 | 功能正常,与原功能一致 |
|
||
| TC-11 | 空列处理 | 对完全无缺失的列执行填补 | 提示"该列无缺失值"或复制原列 |
|
||
| TC-12 | 全缺失列处理 | 对全部缺失的列执行填补 | 提示警告,仍创建新列(全部为填补值) |
|
||
| TC-13 | 重复新列名处理 | 新列名已存在 | 自动添加后缀(如"体重_填补_1")或提示 |
|
||
| TC-14 | 原始数据保留 ⭐ | 填补后,检查原列 | 原列数据完全不变 ✅ |
|
||
|
||
### 边界测试
|
||
|
||
| 测试项 | 场景 | 预期 |
|
||
|--------|------|------|
|
||
| 超大数据集 | 10万行数据执行MICE | 显示进度,不崩溃 |
|
||
| 特殊字符列名 | 列名带括号、等号 | 正常处理(使用columnMapping) |
|
||
| 数据类型混合 | 对文本列执行均值填补 | 提示错误或自动跳过 |
|
||
| 并发处理 | 同时打开多个Dialog | 状态隔离,不互相影响 |
|
||
|
||
---
|
||
|
||
## 📊 性能要求
|
||
|
||
| 操作 | 数据量 | 目标响应时间 |
|
||
|------|--------|--------------|
|
||
| 简单填补(均值/中位数/众数) | 1万行 | < 1秒 |
|
||
| 简单填补 | 10万行 | < 5秒 |
|
||
| MICE填补 | 1万行 | < 10秒 |
|
||
| MICE填补 | 10万行 | < 60秒 |
|
||
| 统计信息获取 | 任意 | < 0.5秒 |
|
||
|
||
---
|
||
|
||
## 🚨 风险和注意事项
|
||
|
||
### 1. 数据安全 ✅ 已解决
|
||
- ✅ 填补操作创建新列,原始数据完全保留
|
||
- ✅ 新列紧邻原列,便于对比验证
|
||
- ✅ 无需撤销功能(原始数据未被修改)
|
||
- ✅ 用户可随时删除填补后的列,或重新填补
|
||
|
||
### 2. MICE性能 ⭐ 重点关注
|
||
- ⚠️ MICE在大数据集上可能很慢(10万行约1分钟)
|
||
- ✅ **必须显示进度条或加载动画**
|
||
- ✅ 添加"预计耗时"提示(基于数据量估算)
|
||
- ✅ 提供"取消执行"按钮(长时间任务)
|
||
- 💡 优化建议:考虑使用Web Worker或后台任务队列
|
||
|
||
### 3. 数据类型兼容性
|
||
- ⚠️ 均值/中位数只适用于数值列
|
||
- ✅ 需要前端验证列的数据类型
|
||
- ✅ 后端也需要校验并返回友好错误
|
||
|
||
### 4. 列名特殊字符
|
||
- ⚠️ 列名可能包含特殊字符
|
||
- ✅ 使用现有的 `columnMapping` 机制
|
||
- ✅ 确保与compute列功能一致
|
||
|
||
### 5. 全部缺失的列
|
||
- ⚠️ 如果列全部为空,均值/中位数为NaN
|
||
- ✅ 需要特殊处理并提示用户
|
||
|
||
---
|
||
|
||
## 📝 依赖项
|
||
|
||
### Python依赖(需要确认)
|
||
```
|
||
pandas >= 1.5.0
|
||
numpy >= 1.23.0
|
||
scikit-learn >= 1.2.0 # ← MICE需要
|
||
```
|
||
|
||
### 前端依赖
|
||
- 无新增依赖(使用现有的Ant Design组件)
|
||
|
||
---
|
||
|
||
## 🎯 验收标准
|
||
|
||
### 必须满足 ⭐
|
||
1. ✅ **MICE功能完全实现**(非常重要!)
|
||
2. ✅ **新列位置正确**(紧邻原列右侧)
|
||
3. ✅ **原始数据完全保留**(填补不修改原列)
|
||
4. ✅ 所有测试用例通过(特别是TC-7, TC-8, TC-14)
|
||
5. ✅ 无Breaking Changes(原有删除功能不受影响)
|
||
6. ✅ UI符合设计稿(3个Tab切换流畅)
|
||
7. ✅ 代码通过Linter检查
|
||
8. ✅ 添加适当的日志和错误处理
|
||
9. ✅ MICE显示进度条或加载动画
|
||
|
||
### 加分项
|
||
1. ⭐ 性能优于预期
|
||
2. ⭐ UI动画流畅
|
||
3. ⭐ 错误提示友好且具体
|
||
4. ⭐ 添加单元测试
|
||
|
||
---
|
||
|
||
## 📅 时间估算(已更新)
|
||
|
||
| 阶段 | 预计时间 | 备注 |
|
||
|------|----------|------|
|
||
| Python后端 - 简单填补 | 40分钟 | fillna.py基础功能 |
|
||
| Python后端 - MICE填补 ⭐ | 50分钟 | **必须实现**,包括sklearn集成 |
|
||
| Python后端 - 新列插入逻辑 | 30分钟 | df.insert()实现,确保新列紧邻原列 |
|
||
| Python - main.py端点 | 20分钟 | 新增3个API端点 |
|
||
| Node.js后端 | 20分钟 | 简单转发 |
|
||
| 前端UI - Tab结构 | 30分钟 | 3个Tab切换 |
|
||
| 前端UI - Tab 2(简单填补) | 40分钟 | 表单 + 统计 + 新列名输入 |
|
||
| 前端UI - Tab 3(MICE) ⭐ | 40分钟 | 多选列 + 参数 + 进度条 |
|
||
| API集成 | 30分钟 | 前端调用后端,处理新列名 |
|
||
| 测试 | 40分钟 | 14个测试用例,重点测试新列位置 |
|
||
| 优化和文档 | 20分钟 | 错误处理 + 文档 |
|
||
| **总计** | **约5-6小时** | **包含完整MICE实现** ⭐ |
|
||
|
||
**说明**:
|
||
- MICE是医学研究的核心需求,必须完整实现
|
||
- 新列插入逻辑需要仔细处理,确保位置正确
|
||
- 前端需要额外时间处理新列名输入和预览
|
||
|
||
---
|
||
|
||
## 📚 参考资料
|
||
|
||
### 缺失值填补理论
|
||
- [sklearn.impute.IterativeImputer文档](https://scikit-learn.org/stable/modules/generated/sklearn.impute.IterativeImputer.html)
|
||
- [MICE算法原理](https://www.jstatsoft.org/article/view/v045i03)
|
||
|
||
### 医学研究中的缺失值处理
|
||
- 均值/中位数填补:最常用,简单快速
|
||
- MICE:高质量研究首选,考虑变量间关系
|
||
- 分组填补:不同人群特征差异大时使用
|
||
|
||
---
|
||
|
||
## ✅ 开发前确认清单
|
||
|
||
已确认事项 ✅:
|
||
|
||
- [x] **MICE功能必须开发**(医学研究核心需求)✅
|
||
- [x] **填补方式:创建新列**(保留原始数据)✅
|
||
- [x] **新列位置:紧邻原列**(便于对比验证)✅
|
||
- [x] **无需撤销功能**(原始数据未被修改)✅
|
||
- [x] UI设计符合预期(3个Tab切换)✅
|
||
- [x] 功能范围合理(Phase 1不包括分组填补、插值等)✅
|
||
- [x] 性能要求合理(MICE 10万行<60秒)✅
|
||
- [x] 测试用例完整(14个测试用例)✅
|
||
- [x] 时间估算可接受(约3-4小时)✅
|
||
|
||
## 🚀 准备开始开发
|
||
|
||
所有确认清单已完成,随时可以开始实施!
|
||
|
||
---
|
||
|
||
## 📝 更新记录
|
||
|
||
### 2025-12-10 更新(用户要求)
|
||
|
||
**新增功能**:
|
||
1. ✅ **前向/后向填充加入本次开发**(原计划在Phase 2)
|
||
- 前向填充(Forward Fill):用前一个非缺失值填充
|
||
- 后向填充(Backward Fill):用后一个非缺失值填充
|
||
- 适用场景:时间序列数据、有顺序的观察数据
|
||
|
||
**影响**:
|
||
- Tab 2新增2个填补选项(共6种方法)
|
||
- Python函数 `fillna_simple` 方法参数新增 `'ffill'` 和 `'bfill'`
|
||
- 测试用例从14个增加到18个
|
||
- 开发时间从5-6小时增加到6-7小时
|
||
|
||
**适用场景说明**:
|
||
- 均值/中位数:适合独立观察的数值变量
|
||
- 众数:适合分类变量
|
||
- 固定值:用户自定义场景
|
||
- **前向填充**:随访数据(如多次测量,用上次值填充)
|
||
- **后向填充**:预测性数据(用未来已知值填充)
|
||
- MICE:需要考虑变量间关系的高质量填补
|
||
|
||
---
|
||
|
||
### 2025-12-09 更新(根据用户确认)
|
||
|
||
**核心变更**:
|
||
1. ✅ **MICE功能必须实现**(医学研究核心需求)
|
||
2. ✅ **填补方式改为创建新列**(保留原始数据)
|
||
3. ✅ **新列位置:紧邻原列右侧**(便于对比验证)
|
||
4. ✅ **取消撤销功能**(原始数据未被修改,无需撤销)
|
||
|
||
**影响**:
|
||
- Python函数签名新增 `new_column_name` 参数
|
||
- UI新增"新列名"输入框
|
||
- 实现逻辑使用 `df.insert()` 确保位置正确
|
||
- 测试用例新增新列位置验证(TC-7, TC-8)
|
||
- 开发时间从3小时增加到5-6小时(MICE+新列逻辑)
|
||
|
||
**优势**:
|
||
- ✅ 原始数据完全保留,数据安全性更高
|
||
- ✅ 新旧数据并列显示,便于验证填补效果
|
||
- ✅ 用户可多次尝试不同填补方法对比
|
||
- ✅ 符合医学研究的严谨性要求
|
||
|
||
---
|
||
|
||
**已确认,准备开始开发!** 🚀
|
||
|