En face de% en%


262

Une variable catégorielle V1 dans une trame de données D1 peut avoir des valeurs représentées par les lettres de A à Z. Je veux créer un sous-ensemble D2, qui exclut certaines valeurs, disons, B, N et T. Fondamentalement, je veux une commande qui est l'opposé de %in%

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

66
pas dedans%? ( !(x %in% y)). La vie peut être facile parfois ...
Joris Meys

Réponses:


355

Vous pouvez utiliser l' !opérateur pour rendre fondamentalement n'importe quel VRAI FAUX et chaque FAUX VRAI. alors:

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

EDIT: Vous pouvez également faire vous-même un opérateur:

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

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

5
L'utilisation de la deuxième option est illustrée dans la page d'aide (correspondance) (où vous obtiendrez si vous avez tapé ?"%in%") où le nouvel opérateur est appelé %w/o%.
IRTFM

23
voir aussi ?Negateeg"%ni%" <- Negate("%in%")
baptiste

2
Negate a fonctionné pour moi lorsqu'il est utilisé après avoir défini le nouvel opérateur, comme suggéré par baptiste, par exemple subset(df, variable %ni% c("A", "B")), mais pas lorsqu'il est utilisé directement, par exemplesubset(df, variable Negate("%in%") c("A", "B"))
PatrickT

2
@PatrickT c'est parce que seuls les opérateurs peuvent être utilisés comme opérateurs. et les opérateurs sont intégrés ou commencent et se terminent par %. Pour créer un opérateur, vous devez affecter une fonction avec deux opérandes à un nom commençant et finissant par %.
vol de moutons


31

Si vous regardez le code de %in%

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

alors vous devriez pouvoir écrire votre version de l'opposé. j'utilise

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

Une autre façon est:

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

excellente solution .. Cela a fonctionné lorsque la négation régulière a échoué.
agatha

17

Voici une version utilisant filterin dplyrqui applique la même technique que la réponse acceptée en niant la logique avec!:

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

12

L'utilisation de negatefrom fait purrrégalement l'affaire rapidement et proprement:

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

Ensuite, l'utilisation est, par exemple,

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

2
Il y a aussi un intégré Negatequi fait la même chose. La seule différence est que Purrr fait appel as_mapperà ce que vous passez, tout en Negateappelant match.fun. rdocumentation.org/packages/purrr/versions/0.2.5/topics/… stat.ethz.ch/R-manual/R-devel/library/base/html/match.fun.html
moutons volants

7

purrr::compose() est un autre moyen rapide de le définir pour une utilisation ultérieure, comme dans:

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

3

Une autre solution pourrait être d'utiliser setdiff

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

D2 = setdiff(D1, D0)

D2 est votre sous-ensemble souhaité.



0

Je pense que l'utilisation la plus claire est

!('Spain' %in% c('Germany', 'France', 'Italy'))

En quoi cela diffère-t-il considérablement des réponses déjà publiées ici?
camille

0
library(roperators)

1 %ni% 2:10

Bien que cela puisse être une bonne réponse, il serait plus utile d'expliquer pourquoi cela fonctionne. Pensez à le modifier pour inclure plus de détails, et si vous pensez que c'est mieux que la réponse acceptée qui a été publiée il y a près d'une décennie.
Jeremy Caney


-1

L'aide pour% in% help("%in%"),, inclut, dans la section Exemples, cette définition de pas dans,

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

Essayons:

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

Alternativement

"%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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.