A categorical variable V1 in a data frame D1 can have values represented by the letters from A to Z. I want to create a subset D2, which excludes some values, say, B, N and T. Basically, I want a command which is the opposite of %in%
D2 = subset(D1, V1 %in% c('B','N',T'))
Instead of creating your own function, it would be useful to just negate the behavior of
needle %in% haystack
do this instead:
!(needle %in% haystack)
this works as well.
purrr::compose()
is another quick way to define this for later use, as in:
`%!in%` <- compose(`!`, `%in%`)
The package collapse has it built in: %!in%
.
Another solution could be using setdiff
D1 = c("A",..., "Z") ; D0 = c("B","N","T")
D2 = setdiff(D1, D0)
D2
is your desired subset.
The help for %in%, help("%in%")
, includes, in the Examples section, this definition of not in,
"%w/o%" <- function(x, y) x[!x %in% y] #-- x without y
Lets try it:
c(2,3,4) %w/o% c(2,8,9)
[1] 3 4
Alternatively
"%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
library(roperators)
1 %ni% 2:10
If you frequently need to use custom infix operators, it is easier to just have them in a package rather than declaring the same exact functions over and over in each script or project.
Hmisc has %nin%
function, which should do this.
https://www.rdocumentation.org/packages/Hmisc/versions/4.4-0/topics/%25nin%25
If you look at the code of %in%
function (x, table) match(x, table, nomatch = 0L) > 0L
then you should be able to write your version of opposite. I use
`%not in%` <- function (x, table) is.na(match(x, table, nomatch=NA_integer_))
Another way is:
function (x, table) match(x, table, nomatch = 0L) == 0L
How about:
'%ni%' <- Negate('%in%')
c(1,3,11) %ni% 1:10
# [1] FALSE FALSE TRUE
This works fine for me:
`%nin%` <- Negate(`%in%`)
require(TSDT)
c(1,3,11) %nin% 1:10
# [1] FALSE FALSE TRUE
For more information, you can refer to: https://cran.r-project.org/web/packages/TSDT/TSDT.pdf
Here is a version using filter
in dplyr
that applies the same technique as the accepted answer by negating the logical with !:
D2 <- D1 %>% dplyr::filter(!V1 %in% c('B','N','T'))
Source: Stackoverflow.com