如何根据行中值的范围/特定值筛选数据列?
Data.table列筛选问题解答
首先初始化示例数据(方便复现):
library(data.table) dt <- structure(list(X1 = c(35L, 45L, 67L, 890L, 23L, 4L, 5L, 34L, 78L, 12L, 3L), X2 = c(100L, 2345L, 3467L, 235L, 46L, 76L, 32L, 17L, 346L, 789L, 32L), X3 = c(345L, 67L, 45L, 342L, 67L, 31L, 6L, 78L, 9L, 34L, 23L), X4 = c(23L, 45L, 657L, 231L, 456L, 342L, 56L, 44567L, 3211L, 2342L, 2L)), row.names = c(NA, -11L), class = c("data.table", "data.frame"))
问题1:用data.table一行代码实现筛选
完全可以,直接利用data.table的.SDcols参数做列选择,一行搞定:
# 筛选包含值5的列(两种写法任选) dt[, .SD, .SDcols = lapply(.SD, function(x) any(x == 5))] # 更简洁的colSums写法 dt[, .SD, .SDcols = colSums(.SD == 5) > 0]
原理:.SDcols接受逻辑向量标记需要保留的列;any(x ==5)判断列中是否存在目标值,colSums(.SD ==5)统计每列符合条件的行数,大于0即说明该列存在目标值。
问题2:指定值范围(如>5 & <1000)
只需要把条件替换成范围判断即可,同样用.SDcols实现:
# 筛选存在值在(5,1000)区间内的列 dt[, .SD, .SDcols = lapply(.SD, function(x) any(x > 5 & x < 1000))] # 简洁版 dt[, .SD, .SDcols = colSums(.SD > 5 & .SD < 1000) > 0]
如果需求是所有行的值都在该范围内,把any换成all即可:
# 筛选所有行值都在(5,1000)区间内的列 dt[, .SD, .SDcols = lapply(.SD, function(x) all(x > 5 & x < 1000))]
问题3:转置后用dplyr的filter_all是否更合适?
没必要,原因如下:
- data.table原生语法已经足够高效简洁,不需要转置这种额外操作,转置会增加内存开销(尤其是大数据集场景)
filter_all是dplyr针对行筛选的工具,转置后将列转为行再筛选属于绕路操作,代码可读性和执行效率都不如直接用data.table原生方法- 如果一定要用dplyr处理,也不需要转置,直接用
select_if即可(和你之前的思路一致):
library(dplyr) dt %>% select_if(~any(.x == 5))
但对于data.table格式的数据,优先使用其原生语法,在大数据量下性能优势明显。
内容的提问来源于stack exchange,提问作者pemb_bex6789
相关产品推荐
相关产品推荐

