%in%的相反操作:排除向量中指定值的行

370

在数据框D1中,分类变量V1的值可以用字母A到Z表示。我想创建一个子集D2,其中排除一些值,比如B、N和T。基本上,我想要一个与%in%相反的命令。

结果:

一个数据框D1中的分类变量V1可以有由字母A到Z表示的值。我想创建一个子集D2,其中排除一些值,比如B、N和T。基本上,我想要一个与%in%相反的命令。

D2 = subset(D1, V1 %in% c("B", "N", "T"))

97
不在其中? (!(x %in% y)). 有时候生活可以很简单…… - Joris Meys
可能是重复的问题:如何从数据框中选择不匹配的行? - Chase
13个回答

481
您可以使用!运算符将任何TRUE变为FALSE,将任何FALSE变为TRUE。因此,代码如下:
D2 = subset(D1, !(V1 %in% c('B','N','T')))

编辑: 您也可以自己创建一个操作符:

'%!in%' <- function(x,y)!('%in%'(x,y))

c(1,3,11)%!in%1:10
[1] FALSE FALSE  TRUE

5
第二个选项的使用在 help(match) 页面中有所说明(如果您键入 ?"%in%" 将会跳转到该页面),其中新操作符被称为 %w/o% - IRTFM
38
另外,请参见?Negate 例如,"%ni%" <- Negate("%in%") - baptiste
2
当按照baptiste的建议定义新操作符后使用Negate时,它对我很有效,例如subset(df, variable %ni% c("A", "B")),但是直接使用时却无效,例如subset(df, variable Negate("%in%") c("A", "B")) - PatrickT
4
那是因为只有运算符才能被用作运算符。运算符要么是内置的,要么以“%”开头和结尾。要创建一个运算符,你需要将一个带有两个操作数的函数赋值给以“%”开头和结尾的名称。 - flying sheep
5
жИСдїђдєЯеПѓдї•дљњзФ®filter(!(V1%in% c('B','N','T')))гАВ - ah bon
显示剩余2条评论

108

如何:

`%ni%` <- Negate(`%in%`)
c(1,3,11) %ni% 1:10
# [1] FALSE FALSE  TRUE

这个程序实际上无法运行,因为它会抛出一个错误,大概是关于 SPECIAL %ni 的问题。 - Flash Thunder
仍然可以正常工作。R版本4.0.3(2020-10-10)平台:x86_64-apple-darwin17.0(64位)运行在:macOS Big Sur 10.16下。 - Spencer Castro
4
由于 ' 不是 \``,所以你应该使用 ``。 - Flash Thunder
更改已经完成。谢谢。 - Spencer Castro

59

这里是使用dplyr中的filter函数的版本,应用了与被接受答案相同的技术,通过否定逻辑运算符!实现:

D2 <- D1 %>% dplyr::filter(!V1 %in% c('B','N','T'))

36

如果您查看%in%的代码

 function (x, table) match(x, table, nomatch = 0L) > 0L

那么你应该能够编写你自己的相反版本。我使用

`%not in%` <- function (x, table) is.na(match(x, table, nomatch=NA_integer_))

另一种方式是:

function (x, table) match(x, table, nomatch = 0L) == 0L

17

使用purrr中的negate函数可以快速而简洁地完成此操作:

`%not_in%` <- purrr::negate(`%in%`)

那么使用方法可以举个例子,

c("cat", "dog") %not_in% c("dog", "mouse")

4
也有一个内置的 "Negate" 可以实现相同的功能。唯一的区别是,purrr 对传递的参数调用了 "as_mapper",而 "Negate" 则调用了 "match.fun"。 - flying sheep

9

purrr::compose()是另一种快速定义以便日后使用的方法,例如:

`%!in%` <- compose(`!`, `%in%`)

6
另一个解决方案可以使用 setdiff
D1 = c("A",..., "Z") ; D0 = c("B","N","T")

D2 = setdiff(D1, D0)

D2 是您所需的子集。


有时它可能很有用,但如果有重复,它不会产生相同的结果。 - skan

3

2
library(roperators)

1 %ni% 2:10

如果您经常需要使用自定义中缀运算符,将它们放在一个包中会比在每个脚本或项目中重复声明完全相同的函数更容易。

虽然这可能是一个正确的答案,但如果能额外解释一下_为什么_它有效,那就更有用了。考虑编辑它以包含更多细节,并且如果你认为它比已经发布近十年的被接受的答案更好的话。 - Jeremy Caney

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接