Odysseus:自托管 AI 工作空间,带来类似 ChatGPT 体验且功能丰富!
2026/6/1 11:40:02
NA(Not Available)表示,但需区分机制:完全随机缺失(MCAR)、随机缺失(MAR)和非随机缺失(MNAR)。识别机制有助于选择合适策略。可通过以下代码快速探查缺失模式:# 加载示例临床数据集 data <- data.frame( age = c(25, NA, 35, 40, NA), blood_pressure = c(120, 130, NA, 140, 135), cholesterol = c(NA, 200, 210, NA, 220) ) # 查看缺失值分布 is.na(data) # 输出逻辑矩阵,TRUE表示缺失 # 统计每列缺失数量 sapply(data, function(x) sum(is.na(x)))| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 删除法 | 缺失比例极低 | 简单高效 | 损失信息,可能导致偏倚 |
| 均值/中位数填充 | 数值型变量,MCAR | 保持样本量 | 低估方差,扭曲分布 |
| 多重插补(MICE) | MAR或复杂结构 | 保留统计性质 | 计算复杂,需建模假设 |
visdat包可直观展示缺失结构:# 安装并加载可视化工具 library(visdat) vis_miss(data) # 生成热力图式缺失图谱正确识别与处理缺失值,是保障临床数据分析科学性的第一道防线。# 使用logistic回归检验缺失是否与观测变量相关 missing_model <- glm(is.na(depression_score) ~ age + gender, family = binomial, data = clinical_data) summary(missing_model)该代码拟合一个逻辑回归模型,判断缺失概率是否受年龄或性别影响。若系数显著,则属于MAR而非MCAR。# 示例数据框 df <- data.frame(x = c(1, NA, 3), y = c(NA, "b", "c")) is.na(df)该函数返回逻辑矩阵,TRUE表示对应位置为缺失值。结合sum(is.na(df))可统计总缺失数,适用于精确追踪缺失位置。summary(df)summary()按列输出变量统计信息,对因子和字符型显示频数,数值型显示分位数,并明确标注NA's数量,适合快速评估各字段完整性。is.na()精准定位每一个缺失点summary()提供高层缺失概览library(naniar) vis_miss(airquality, cluster = TRUE)该代码生成基于聚类排序的缺失热图,深色区域表示缺失值位置。`vis_miss`函数通过颜色映射将NA值可视化,帮助识别变量间缺失是否具有相关性。| Original | Shadow |
|---|---|
| 25 | no |
| NA | yes |
缺失率定义为某字段空值数量占总记录数的比例:
missing_rate = df.isnull().sum() / len(df)该代码计算每列的缺失比例,isnull()标记空值,sum()统计每列空值总数,除以总行数得到比率。
import pandas as pd def compute_missing_rate(df, site_name): missing_stats = df.isnull().sum() total_counts = df.shape[0] missing_rate = (missing_stats / total_counts) * 100 return pd.DataFrame({ 'site': site_name, 'missing_rate': missing_rate }) # 应用于中心A和中心B rate_a = compute_missing_rate(center_a_df, "Center_A") rate_b = compute_missing_rate(center_b_df, "Center_B")该函数逐列计算缺失占比,便于横向对比。结果可进一步聚合为缺失热力图或对比表格。| Field | Center A (%) | Center B (%) | Center C (%) |
|---|---|---|---|
| LVEF | 12.3 | 6.7 | 23.1 |
| HbA1c | 8.5 | 15.2 | 9.8 |
func BatchDelete(ids []string) error { for _, id := range ids { if err := DeleteSingle(id); err != nil { log.Warn("部分删除失败", "id", id) } } return nil }该模式通过循环调用单例删除接口实现,优势在于逻辑清晰、实现简单。但缺乏原子性保障,可能引发数据残留。import pandas as pd # 按类别分组填补均值 df['age_filled'] = df.groupby('gender')['age'].transform( lambda x: x.fillna(x.mean()) )该方法保留了组内特征,减少跨组偏差。对于极端分布,可改用中位数或 Winsorized 均值。from sklearn.linear_model import LinearRegression import numpy as np # 示例:使用线性回归填补年龄缺失 X_train = df_non_missing[['income', 'experience']] # 完整样本的特征 y_train = df_non_missing['age'] # 完整的年龄值 X_missing = df_missing[['income', 'experience']] # 缺失样本的特征 model = LinearRegression() model.fit(X_train, y_train) predicted_age = model.predict(X_missing)上述代码通过收入和工作经验预测缺失年龄,核心在于建立特征间的定量关系。library(mice) md.pattern(airquality)该代码展示`airquality`数据集的缺失模式表,帮助理解变量间缺失结构。imp <- mice(airquality, m = 5, method = "pmm", maxit = 50)其中,`m = 5`表示生成5个插补数据集,`method = "pmm"`采用预测均值匹配,适用于连续变量;`maxit = 50`设定最大迭代次数以确保收敛。 最终通过`with()`和`pool()`完成分析与结果整合,实现对参数估计的偏差校正。import pandas as pd df['value'] = df['value'].fillna(method='ffill')该方法实现简单,但可能低估波动性,过度使用易引入偏倚。df['value'] = df['value'].interpolate(method='linear', limit_direction='both')此方法利用时间维度信息,更真实反映生理参数演变过程,尤其适用于密集纵向数据。library(impute) knn_data <- impute.knn(expression_matrix, k = 10) filled_data <- knn_data$data该代码调用R语言impute包,设置k=10表示使用10个最近邻样本进行加权插补,适用于行(基因)方向不变、列(样本)间比较的组学数据结构。from scipy import stats import numpy as np # 原始数据 x_original(含缺失),插补后数据 x_imputed ks_stat, p_value = stats.ks_2samp(x_original[~np.isnan(x_original)], x_imputed) print(f"KS检验p值: {p_value:.3f}")该代码使用双样本K-S检验比较原始观测值与插补值的分布差异。若p值 > 0.05,表明两者分布无显著差异,插补未引入显著偏移。[分布密度对比图:原始数据 vs 插补数据]
import pandas as pd from scipy import stats def detect_outliers(df, column): z_scores = stats.zscore(df[column]) return df[(abs(z_scores) > 3)] # Z-score > 3 视为离群值 # 应用于血清肌酐检测数据 outliers = detect_outliers(lab_data, 'creatinine_level') print(f"发现 {len(outliers)} 条异常记录")| 数据源 | 接口协议 | 同步频率 | 加密方式 |
|---|---|---|---|
| Epic EHR | FHIR API | 每小时 | TLS 1.3 + OAuth2 |
| Fitbit Devices | RESTful JSON | 实时流 | AES-256 |