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.