R中使用filter与map函数基于IQR规则批量过滤多列离群值
解决R数据框多列按IQR规则批量移除离群值的方案
原代码问题说明
- 每次过滤都基于原始数据集,没有继承上一轮的过滤结果,循环结束后仅保留了最后一列的过滤规则
- 同一列的上下限过滤是分别对原始数据执行,前一次的下限过滤结果直接被后一次覆盖,实际只生效了上限过滤规则
实现方案
完全可以用filter搭配purrr的map系列函数实现,也可以用dplyr内置的if_all更简洁实现:
步骤1:定义非离群值判断函数
library(tidyverse) # 自定义判断单向量非离群值的函数,默认自动忽略NA is_non_outlier <- function(x) { q <- quantile(x, c(0.25, 0.75), na.rm = TRUE) iqr <- IQR(x, na.rm = TRUE) x >= (q[1] - 1.5 * iqr) & x <= (q[2] + 1.5 * iqr) }
方案1:用filter + if_all实现(最简洁)
适合需要对所有列/指定列生效,保留所有列都不存在离群值的行:
# 对所有列应用规则,过滤出所有列都是非离群值的行 df_filtered <- df %>% filter(if_all(everything(), is_non_outlier)) # 如果只需要对指定列应用规则,比如仅对aa、bb列过滤,写法如下 # df_filtered <- df %>% # filter(if_all(c(aa, bb), is_non_outlier))
方案2:用filter + map实现(符合要求的map用法)
通过map生成每列的判断条件,再按行逻辑与合并后过滤:
# 生成所有列的非离群值判断向量,按行取与合并为过滤条件 filter_cond <- map(df, is_non_outlier) %>% reduce(`&`) # 应用过滤条件 df_filtered <- df %>% filter(filter_cond)
结果验证
用示例数据测试,原始数据共13行,过滤后共11行,成功移除了第1行(cc列为-9属于离群值)和第13行(aa为15、cc为25属于离群值),符合预期。
内容的提问来源于stack exchange,提问作者gus079
相关产品推荐
相关产品推荐

