如何移除列表中过滤后行数为零的tibble?求compact替代方案
解决tibble列表过滤后移除0行对象的问题
你遇到的问题很常见——purrr::compact()确实没法处理这种有列结构但0行的tibble,因为它的作用是移除完全为空的元素(比如NULL、空列表),而0行的tibble本质上还是一个有效的数据框对象,所以compact识别不出来。
这里给你两个简洁的解决方案,都用tidyverse工具链实现:
方法一:map() + keep() 组合
先对列表里的每个tibble执行过滤,再筛选出过滤后行数大于0的对象:
library(tidyverse) # 构造符合你场景的示例列表 mylst <- lst( cars1 = as_tibble(cars), cars2 = as_tibble(cars) %>% mutate(speed = speed + 100), # 过滤后会变成0行 cars3 = as_tibble(cars) %>% filter(dist > 100) # 本身就是0行 ) # 一步完成过滤+筛选 final_lst <- mylst %>% # 对每个tibble执行你的过滤条件,这里以speed < 20为例 map(~ filter(.x, speed < 20)) %>% # 保留行数大于0的tibble keep(~ nrow(.x) > 0)
方法二:map() + discard() 组合
如果你习惯反向筛选(移除不符合条件的),可以用discard()替代keep():
final_lst <- mylst %>% map(~ filter(.x, speed < 20)) %>% # 移除行数等于0的tibble discard(~ nrow(.x) == 0)
关键说明
keep()和discard()都是purrr里的列表筛选函数,支持自定义判断条件,完美适配你需要检查行数的场景。- 因为你明确所有tibble都有目标列,所以不用额外处理列不存在的情况;如果后续有列不统一的场景,可以加个
has_name()的判断,比如keep(~ has_name(.x, "speed") && nrow(.x) > 0)。
内容的提问来源于stack exchange,提问作者jzadra
相关产品推荐
相关产品推荐

