计算Cook距离后,如何删除多元回归的影响值以清理R数据框?
解决方案:移除Cook距离标记的异常行
首先先修正你代码里的小问题:需要提前初始化存储模型、Cook距离等的空列表,避免运行时出现未定义对象的报错:
data(varechem, package = "vegan") data(varespec, package = "vegan") vare <- cbind(varespec, varechem) # 提前初始化空列表,避免报错 mod_cook <- list() cook_distance <- list() influential <- list() names_influencial <- list() for (j in c("Callvulg", "Empenigr")){ for (soil in c("N", "K", "S", "P", "Fe")){ mod_name <- paste( soil, j, sep="_") cook_name <- paste( soil, j, sep="_") name <- paste( soil, j, sep="_") outliers <- paste( soil, j, sep="_") mod_cook[[mod_name]] <- lm(vare[,j] ~ vare[,soil], na.action = na.exclude) cook_distance[[cook_name]] <- cooks.distance(mod_cook[[mod_name]]) sample_size <- nrow(vare) influential[[name]] <- which(cook_distance[[cook_name]] > 4/sample_size) names_influencial[[outliers]] <- names(influential[[name]]) } }
接下来根据你的需求,分两种场景实现异常行移除:
场景1:全局移除所有模型标记的异常行(去重)
如果要把所有回归模型中检测到的异常行一次性从原数据框vare中移除,只保留从未被标记为异常的行:
# 收集所有模型的异常行号并去重 all_outliers <- unique(unlist(influential)) # 移除异常行,生成清理后的全局数据集 vare_clean_global <- vare[-all_outliers, ]
场景2:为每个模型单独生成移除对应异常后的数据集
如果需要为每一组(土壤变量+物种)的回归模型单独保留移除该模型异常行后的数据集,可以用以下两种方式:
方式1:在原循环内直接生成
修改循环代码,每次计算完异常行后立即生成对应清理数据集:
# 初始化存储各模型清理后数据集的列表 vare_clean_list <- list() for (j in c("Callvulg", "Empenigr")){ for (soil in c("N", "K", "S", "P", "Fe")){ mod_name <- paste( soil, j, sep="_") cook_name <- paste( soil, j, sep="_") name <- paste( soil, j, sep="_") outliers <- paste( soil, j, sep="_") mod_cook[[mod_name]] <- lm(vare[,j] ~ vare[,soil], na.action = na.exclude) cook_distance[[cook_name]] <- cooks.distance(mod_cook[[mod_name]]) sample_size <- nrow(vare) influential[[name]] <- which(cook_distance[[cook_name]] > 4/sample_size) names_influencial[[outliers]] <- names(influential[[name]]) # 生成当前模型对应的清理后数据集 vare_clean_list[[mod_name]] <- if(length(influential[[name]]) > 0) { vare[-influential[[name]], ] } else { vare # 无异常行时直接保留原数据 } } }
之后可通过vare_clean_list[["N_Callvulg"]]这类索引获取对应模型的清理数据集。
方式2:事后批量生成
如果已经跑完原循环,也可以事后遍历influential列表生成:
vare_clean_list <- list() for (model_name in names(influential)) { vare_clean_list[[model_name]] <- if(length(influential[[model_name]]) > 0) { vare[-influential[[model_name]], ] } else { vare } }
额外注意点
- 你用的
4/sample_size是Cook距离常用的异常判断阈值,若样本量较大,也可考虑用1作为阈值; na.action = na.exclude会让lm跳过缺失值,which()会自动忽略Cook距离结果中的NA,无需额外处理;- 移除异常行后建议重新拟合模型,验证拟合效果,避免过度删除数据导致分析偏差。
内容的提问来源于stack exchange,提问作者i.b
相关产品推荐
相关产品推荐

