R语言tidyverse如何筛选与参考向量完全匹配的嵌套数据
问题
如何筛选嵌套数据集,保证嵌套内容与指定参考向量或tibble完全一致?
初始测试代码如下:
library(tidyverse) rev_vec <- c("apple", "pear", "banana") df <- tibble( ID= rep(1:3, each =3), fruits = c("apple", "pear", "banana", "Pineapple", "Pineapple", "orange", "lime", "pear", NA)) df_vec <- df %>% group_by(ID) %>% summarise(fruits = list(unique(fruits))) ## 以下写法均无法实现需求 df_vec %>% filter(fruits == rev_vec) df_vec %>% filter(unlist(fruits) == rev_vec) df_vec %>% filter(all(unlist(fruits[[1]]) ==rev_vec))
核心需求:找出与参考向量匹配的ID,本示例中正确匹配的ID为1。
预期结果
仅保留ID=1的行,输出格式如下:
# A tibble: 1 x 2 ID fruits <int> <list> 1 1 <chr [3]>
解决方案
嵌套列表列的逐行判断需要借助purrr包的遍历函数逐行校验,不能直接用普通向量比较逻辑,补全后的筛选代码如下:
df_vec %>% filter(map_lgl(fruits, ~identical(.x, rev_vec)))
判断逻辑说明
map_lgl会逐行遍历fruits列的每一个嵌套向量,返回和原表行数一致的逻辑值向量,供filter做行筛选identical会做严格等值校验:要求两个向量的元素内容、顺序、长度、数据类型完全一致,符合完全匹配的要求- 如果不需要匹配顺序,仅要求元素集合完全重合,可以把判断逻辑替换为
setequal(.x, rev_vec),该函数会自动忽略元素顺序、自动去重后校验集合一致性
原写法失效原因
- 直接用
fruits == rev_vec:列表列和原子向量类型不匹配,无法直接做向量化比较 unlist(fruits) == rev_vec:会把所有行的嵌套元素拆成一个长向量做循环比对,返回的逻辑向量长度和原表行数不一致,筛选结果错乱all(unlist(fruits[[1]]) ==rev_vec):固定取第一行的嵌套元素做判断,不会逐行遍历每个ID对应的水果向量,所有行的判断结果都和第一行绑定,无法正确筛选其他行的匹配情况
内容的提问来源于stack exchange,提问作者L Smeets
相关产品推荐
相关产品推荐

