如何智能逐列比较多变量并过滤差距小于5%的数据?
更简洁的实现方式
针对变量增多后代码冗余的问题,有几种更智能的实现思路,不用手动写所有两两变量的判断:
方法一:利用两两组合自动判断(通用场景)
通过combn生成所有变量的两两组合,批量判断每个组合的相对差异是否符合条件,不管变量数量多少都能自动适配:
library(tidyverse) diamonds %>% select(x, y, z) %>% rowwise() %>% filter( # 生成当前行所有变量的两两组合,逐个判断相对差异 combn(c_across(everything()), 2, function(pair) abs(pair[1] - pair[2]) / max(pair[1], pair[2]) < 0.05) %>% all() # 确保所有组合都满足条件 ) %>% ungroup()
如果担心rowwise的效率,也可以用pmap实现:
diamonds %>% select(x, y, z) %>% filter( pmap_lgl(., ~ { vals <- c(...) combn(vals, 2, function(pair) abs(pair[1]-pair[2])/max(pair[1], pair[2]) < 0.05) %>% all() }) )
方法二:利用最大最小值简化判断(更高效)
其实可以换个逻辑:如果一行中最大值和最小值的相对差异小于5%,那么所有两两变量的差异必然都小于5%(因为任意两个变量的差值不会超过最大最小值的差,且分母不会大于最大值)。这个思路计算量更小,代码更简洁:
library(tidyverse) diamonds %>% select(x, y, z) %>% rowwise() %>% filter( # 最小值/最大值 > 0.95,等价于相对差异小于5% min(c_across(everything())) / max(c_across(everything())) > 0.95 ) %>% ungroup()
如果要进一步优化效率,可以用matrixStats包的行统计函数替代rowwise,避免逐行循环:
library(tidyverse) library(matrixStats) diamonds %>% select(x, y, z) %>% filter(rowMins(.) / rowMaxs(.) > 0.95)
这个方法速度更快,适合处理大数据集。
内容的提问来源于stack exchange,提问作者anderwyang
相关产品推荐
相关产品推荐

