如何基于非嵌套字符向量对Purrr嵌套数据进行条件筛选?
嵌套数据框的条件筛选解决方案
没问题,我来帮你搞定这个嵌套数据的条件筛选需求。首先得先修正一下你提供的df2代码——直接把vec1/vec2放进tribble会报错,因为它们是长度大于1的向量,得用list()把它们包起来,不然会出现列长度不匹配的问题。先把完整的可复现代码放出来:
library(tidyverse) vec1 <- c("A", "B") vec2 <- c("A", "B", "C") # 生成嵌套的df1 df1 <- tibble::tribble( ~A, ~B, "X", 4L, "X", 9L, "Y", 5L, "Y", 2L, "Y", 8L, "Y", 2L ) %>% group_by(A) %>% nest() # 修正后的df2:用list()包裹向量,确保列类型统一为列表 df2 <- tibble::tribble( ~A, ~C, "X", list(vec1), "Y", list(vec2) ) # 合并得到df3 df3 <- df1 %>% left_join(df2, by = "A")
接下来就是核心的筛选逻辑:我们可以用dplyr::case_when结合purrr系列函数,根据C列的不同值(vec1或vec2)对嵌套的data列应用不同的筛选规则。假设你说的“对应条件”是筛选B > 3(你可以根据实际需求替换成自己的条件),代码如下:
# 生成筛选后的df4 df4 <- df3 %>% mutate(data = case_when( # 判断当前行的C是否等于vec1(因为C是列表,用map_lgl逐个检查) map_lgl(C, ~identical(.x, vec1)) ~ map(data, ~filter(.x, B < 5)), # 判断当前行的C是否等于vec2,应用对应筛选条件 map_lgl(C, ~identical(.x, vec2)) ~ map(data, ~filter(.x, B > 3)), # 如果有其他未匹配的C值,默认保留原数据(也可以改成~list(tibble())来清空) TRUE ~ data )) # 展开嵌套数据查看结果 df4 %>% unnest(data)
代码解释:
map_lgl(C, ~identical(.x, vec1)):因为C列是列表类型,所以用map_lgl遍历每个列表元素,判断是否和vec1完全一致,返回逻辑值用于case_when的分支判断。map(data, ~filter(.x, B < 5)):对符合条件的行,用map遍历嵌套的data数据框,应用filter筛选出B < 5的行。- 对于
vec2对应的分支,你只需要把filter(.x, B > 3)替换成你实际需要的筛选条件即可(比如B %% 2 == 0筛选偶数,或者B %in% c(2,5)等)。
运行上面的代码后,df4就是你需要的筛选后的嵌套数据框,展开后可以看到:
- 对于
A="X"(对应C=vec1),只保留了B=4的行; - 对于
A="Y"(对应C=vec2),保留了B=5和B=8的行(符合B>3的条件)。
内容的提问来源于stack exchange,提问作者Geet
相关产品推荐
相关产品推荐

