tidyverse中filter嵌套%in%与pull()失效问题求助
问题分析与解决
报错原因
你嵌套使用管道时没有给内部的管道表达式加括号,R的语法解析会把mydf |> filter(duplicated(...)) |> pull(mpg)当成filter()函数的第二个参数,而非先计算出mpg向量再传入%in%,导致类型不匹配报错。
快速修复原代码
给内部的整个管道表达式加上括号,让R优先计算出需要的mpg向量:
mydf |> filter(mpg %in% (mydf |> filter(duplicated(paste0(cyl,am,vs))) |> pull(mpg)))
更准确满足需求的方案
不过上述修复后的代码存在逻辑漏洞:duplicated()仅标记第二次及以后出现的重复项,你pull出的只是重复组中非首次行的mpg,如果同一组内首次行的mpg和其他行不同,这行就会被漏掉,无法实现“包含重复组所有观测值”的需求。
推荐用以下更可靠的方法:
方法1:分组筛选(最简洁)
直接按cyl+am+vs分组,筛选出组内观测数大于1的所有行:
library(tidyverse) mydf <- tibble(mtcars) mydf |> group_by(cyl, am, vs) |> filter(n() > 1) |> ungroup()
方法2:用半连接筛选
先提取出重复的组合,再通过半连接保留所有属于这些组合的观测:
# 第一步:找出出现次数大于1的cyl+am+vs组合 duplicate_groups <- mydf |> count(cyl, am, vs) |> filter(n > 1) # 第二步:筛选出属于这些组合的所有行 mydf |> semi_join(duplicate_groups, by = c("cyl", "am", "vs"))
方法3:直接匹配重复组合(替代原思路)
如果坚持用%in%的逻辑,应该直接匹配组合字符串而非mpg,避免mpg重复带来的误判:
mydf |> filter( paste0(cyl, am, vs) %in% (mydf |> filter(duplicated(paste0(cyl, am, vs))) |> pull(paste0(cyl, am, vs))) )
内容的提问来源于stack exchange,提问作者Yann
相关产品推荐
相关产品推荐

