Features - User Management (Phase 4.1): - Database: Add user_modules table for fine-grained module permissions - Database: Add 4 user permissions (view/create/edit/delete) to role_permissions - Backend: UserService (780 lines) - CRUD with tenant isolation - Backend: UserController + UserRoutes (648 lines) - 13 API endpoints - Backend: Batch import users from Excel - Frontend: UserListPage (412 lines) - list/filter/search/pagination - Frontend: UserFormPage (341 lines) - create/edit with module config - Frontend: UserDetailPage (393 lines) - details/tenant/module management - Frontend: 3 modal components (592 lines) - import/assign/configure - API: GET/POST/PUT/DELETE /api/admin/users/* endpoints Architecture Upgrade - Module Permission System: - Backend: Add getUserModules() method in auth.service - Backend: Login API returns modules array in user object - Frontend: AuthContext adds hasModule() method - Frontend: Navigation filters modules based on user.modules - Frontend: RouteGuard checks requiredModule instead of requiredVersion - Frontend: Remove deprecated version-based permission system - UX: Only show accessible modules in navigation (clean UI) - UX: Smart redirect after login (avoid 403 for regular users) Fixes: - Fix UTF-8 encoding corruption in ~100 docs files - Fix pageSize type conversion in userService (String to Number) - Fix authUser undefined error in TopNavigation - Fix login redirect logic with role-based access check - Update Git commit guidelines v1.2 with UTF-8 safety rules Database Changes: - CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled) - ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code) - INSERT 4 permissions + role assignments - UPDATE PUBLIC tenant with 8 module subscriptions Technical: - Backend: 5 new files (~2400 lines) - Frontend: 10 new files (~2500 lines) - Docs: 1 development record + 2 status updates + 1 guideline update - Total: ~4900 lines of code Status: User management 100% complete, module permission system operational
6.4 KiB
6.4 KiB
工具 C:AI 辅助医疗数据清洗场景分级清单
这份清单按技术实现难度和业务逻辑复杂度从简单到复杂排列。所有场景均假设数据已加载为 Pandas DataFrame (df)。
Level 1: 基础卫生清理 (Data Hygiene)
目标:把“脏”数据变成“能读”的数据。Excel 也能做,但 Python 更快更准。
1.1 变量名标准化 (Rename)
- 场景: 原始表头是中文或含特殊符号(年龄(岁), 性别/Gender, 入院_日期),SPSS 报错。
- 用户指令: “把所有列名转为纯英文小写,去掉括号。”
- Python 逻辑: 使用映射字典或正则替换列名。
1.2 数值列“排毒” (Clean Numeric)
- 场景: 检验科导出的数据,数值列混入了符号(>100, <0.1, 12.5+, 未查)。
- 用户指令: “把‘肌酐’列里的非数字符号去掉,‘<0.1’按‘0.05’处理,转为浮点数。”
- Python 逻辑: str.replace + 正则提取 + pd.to_numeric(errors='coerce')。
1.3 统一缺失值 (Standardize Nulls)
- 场景: 数据里混杂了各种代表“空”的词:NA, N/A, -, \, 不详。
- 用户指令: “把所有代表‘没有’的字符都统一替换为标准的空值。”
- Python 逻辑: df.replace(['-', '不详', 'NA'], np.nan, inplace=True)。
Level 2: 变量标准化与重编码 (Recode & Standardization)
目标:为统计分析准备分类变量。
2.1 文本转数值映射 (Map Categorical)
- 场景: 性别列是 Male/Female,吸烟史是 Yes/No。
- 用户指令: “把性别转为 1(男)/0(女),把吸烟史转为 1/0。”
- Python 逻辑: df['sex'].map({'Male': 1, 'Female': 0})。
2.2 连续变量分箱 (Binning)
- 场景: 需要按年龄分组进行卡方检验。
- 用户指令: “把年龄按 0-18, 19-60, 60+ 分为‘未成年’, ‘成年’, ‘老年’三组。”
- Python 逻辑: pd.cut() 函数。
2.3 复杂日期计算 (Date Logic)
- 场景: 计算生存时间(OS)。Excel 经常算错闰年或月份。
- 用户指令: “根据‘确诊日期’和‘随访日期’计算生存月数,保留1位小数。”
- Python 逻辑: (df['end_date'] - df['start_date']).dt.days / 30.4。
Level 3: 临床逻辑特征工程 (Feature Engineering)
目标:基于医学知识生成新的分析指标。
3.1 复合公式计算 (Complex Formula)
- 场景: 计算 eGFR (肾小球滤过率) 或 BMI。
- 用户指令: “帮我计算 BMI。如果 BMI > 28,生成新列标记为‘肥胖’。”
- Python 逻辑: 向量化计算 df['weight'] / (df['height']/100)**2 + 条件赋值 np.where。
3.2 提取入排标准 (Cohort Selection)
- 场景: 筛选符合条件的入组人群。
- 用户指令: “筛选出:确诊为肺腺癌,且年龄大于18岁,且没有高血压病史的病人。”
- Python 逻辑: df.query("diagnosis == 'Lung Adenocarcinoma' & age > 18 & hypertension == 0")。
3.3 哑变量生成 (One-Hot Encoding)
- 场景: 准备做 Logistic 回归,有一个无序多分类变量“血型 (A, B, AB, O)”。
- 用户指令: “把血型生成哑变量。”
- Python 逻辑: pd.get_dummies(df['blood_type'], prefix='blood')。
Level 4: 结构重塑与高级治理 (Reshaping & Governance)
目标:改变表格结构以适应特定的统计模型,或进行高阶数据修复。
4.1 长宽表转换 (Pivot/Melt) —— Excel 的噩梦
- 场景: 目前是“一人多行”(张三-第1次化验,张三-第2次化验),要做重复测量分析,需要变成“一人一行”(张三-化验1-化验2)。
- 用户指令: “把表格从长表转为宽表,按病人ID索引,用‘访视次序’做后缀,铺开‘白细胞’列。”
- Python 逻辑: df.pivot(index='id', columns='visit', values='wbc')。
4.2 智能去重 (Smart Deduplication)
- 场景: 同一个病人有两条记录,一条信息全,一条信息缺。
- 用户指令: “按病人ID去重。如果有重复,保留‘检查日期’最近的那一条;如果日期一样,保留‘数据完整度’最高的那条。”
- Python 逻辑: df.sort_values(['date', 'completeness']).drop_duplicates(subset=['id'], keep='last')。
4.3 跨列逻辑校验 (Cross-Check)
- 场景: 发现脏数据。
- 用户指令: “检查一下有没有‘男性’但是‘怀孕次数>0’的错误数据,标记出来。”
- Python 逻辑: df.loc[(df['sex']=='男') & (df['preg_count']>0), 'error_flag'] = 1。
4.4 多重插补 (Multiple Imputation) —— 统计学的高级填补
-
场景: 数据集有缺失值(如 BMI 缺失),单纯用均值填补会破坏数据分布。需要利用其他变量(如年龄、性别、肌酐)的相关性来预测填补。
-
用户指令: “使用多重插补法(MICE)对‘BMI’和‘年龄’列的缺失值进行填补。”
-
Python 逻辑: ```python from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer 仅针对数值列进行插补 cols = ['bmi', 'age', 'creatinine'] imp = IterativeImputer(max_iter=10, random_state=0) df[cols] = imp.fit_transform(df[cols])
Level 5: 非结构化文本挖掘 (Text Mining) —— Python 的绝对统治区
目标:从备注或报告文本中“抠”出数据。这是 Excel 绝对做不到的。
5.1 正则表达式提取 (Regex Extraction)
- 场景: 只有一列文本“病理诊断”,内容如:“(左肺上叶)浸润性腺癌,大小3.5*2cm”。需要提取肿瘤大小。
- 用户指令: “从‘病理诊断’里提取出肿瘤的长径(最大的那个数字)。”
- Python 逻辑: df['text'].str.extract(r'(\d+\.?\d*)\s*[\*xX]\s*(\d+\.?\d*)') 并取最大值。
5.2 字符串模糊匹配 (Fuzzy Matching)
- 场景: 医院名称录入混乱:“协和医院”、“北京协和”、“协和”。需要统一。
- 用户指令: “把‘医院名称’列里所有包含‘协和’的,都统一改为‘PUMCH’。”
- Python 逻辑: df.loc[df['hospital'].str.contains('协和'), 'hospital'] = 'PUMCH'。