与%in%相反


262

数据帧D1中的分类变量V1可以具有由字母A到Z表示的值。我想创建一个子集D2,其中不包括某些值,例如B,N和T。基本上,我想要一个命令相反的 %in%

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

66
不是%in%?(!(x %in% y))。有时候生活会很轻松……
Joris Meys

Answers:


354

您可以使用!运算符从根本上将任何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%"调用了new运算符%w/o%
IRTFM

23
也可参见?Negate"%ni%" <- Negate("%in%")
巴蒂斯特

2
根据baptiste的建议,subset(df, variable %ni% c("A", "B"))subset(df, variable Negate("%in%") c("A", "B"))
Negate

2
@PatrickT,因为只有运算符可以用作运算符。并且运算符是内置的或以开头和结尾%。要创建运算符,您需要将一个具有两个操作数的函数分配给以和开头的名称%
飞羊


31

如果您看一下 %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

极好的解决方案。当常规否定失败时,它会起作用。
agatha 2012年

17

下面是使用一个版本filterdplyr,通过否定逻辑与应用相同的技术接受的答案!

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


7

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

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

3

另一个解决方案可能是使用 setdiff

D1 = c("A",..., "Z") ; D0 = c("B","N","T")

D2 = setdiff(D1, D0)

D2 是您想要的子集。




0
library(roperators)

1 %ni% 2:10

尽管这可能是一个正确的答案,但对它为什么起作用的附加说明会更有用。考虑编辑它以包含更多详细信息,如果您觉得它比十年前发布的公认答案更好。
杰里米·卡尼


-1

help("%in%")在示例部分中,%in%的帮助包括not in的定义,

"%w/o%" <- function(x, y) x[!x %in% y] #-- x without y

让我们尝试一下:

c(2,3,4) %w/o% c(2,8,9)
[1] 3 4

或者

"%w/o%" <- function(x, y) !x %in% y #--  x without y
c(2,3,4) %w/o% c(2,8,9)
# [1] FALSE  TRUE  TRUE
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.