Frente a% en%


262

Una variable categórica V1 en un marco de datos D1 puede tener valores representados por las letras de la A a la Z. Quiero crear un subconjunto D2, que excluye algunos valores, por ejemplo, B, N y T. Básicamente, quiero un comando que sea lo contrario a %in%

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

66
no en%? ( !(x %in% y)) La vida puede ser fácil a veces ...
Joris Meys

Respuestas:


355

Puedes usar el !operador para hacer básicamente cualquier VERDADERO FALSO y cada FALSO VERDADERO. entonces:

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

EDITAR: También puede hacer un operador usted mismo:

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

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

55
El uso de la segunda opción se ilustra en la página de ayuda (coincidencia) (donde llegaría si escribiera ?"%in%") donde se llama al nuevo operador %w/o%.
IRTFM

23
ver también, ?Negatepor ejemplo"%ni%" <- Negate("%in%")
baptiste

2
Negate trabajó para mí cuando lo usé después de definir el nuevo operador, como lo sugirió baptiste, por ejemplo subset(df, variable %ni% c("A", "B")), pero no cuando lo usé directamente, por ejemplosubset(df, variable Negate("%in%") c("A", "B"))
PatrickT

2
@PatrickT es porque solo los operadores pueden ser utilizados como operadores. y los operadores están integrados o comienzan y terminan con %. Para crear un operador, debe asignar una función con dos operandos a un nombre que comience y termine con %.
ovejas voladoras


31

Si nos fijamos en el código de %in%

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

entonces deberías poder escribir tu versión de opuesto. yo suelo

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

Otra forma es:

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

excelente solución ... funcionó cuando la negación regular falló.
agatha

17

Aquí hay una versión que usa filterin dplyrque aplica la misma técnica que la respuesta aceptada al negar la lógica con!

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

12

Usar negatefrom purrrtambién hace el truco de forma rápida y ordenada:

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

Entonces el uso es, por ejemplo,

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

2
También hay un incorporado Negateque hace lo mismo. La única diferencia es que el ronroneo llama as_mappera lo que pasa, mientras que las Negatellamadas match.fun. rdocumentation.org/packages/purrr/versions/0.2.5/topics/… stat.ethz.ch/R-manual/R-devel/library/base/html/match.fun.html
ovejas voladoras el

7

purrr::compose() Es otra forma rápida de definir esto para su uso posterior, como en:

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

3

Otra solución podría estar usando setdiff

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

D2 = setdiff(D1, D0)

D2 es tu subconjunto deseado.



0

Creo que el uso más claro es solo

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

¿Cómo difiere esto sustancialmente de las respuestas ya publicadas aquí?
camille

0
library(roperators)

1 %ni% 2:10

Si bien esta puede ser una respuesta correcta, sería más útil con una explicación adicional de por qué funciona. Considere editarlo para incluir más detalles, y si cree que es mejor que la respuesta aceptada que se publicó hace casi una década.
Jeremy Caney


-1

La ayuda para% en%, help("%in%")incluye, en la sección de Ejemplos, esta definición de no en,

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

Vamos a intentarlo:

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

Alternativamente

"%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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.