Naprzeciwko% w%


262

Zmienna jakościowa V1 w ramce danych D1 może mieć wartości reprezentowane przez litery od A do Z. Chcę utworzyć podzbiór D2, który wyklucza niektóre wartości, powiedzmy B, N i T. Zasadniczo chcę polecenia, które jest przeciwieństwo %in%

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

66
nie w%? ( !(x %in% y)). Czasami życie może być łatwe ...
Joris Meys,

Odpowiedzi:


354

Możesz użyć !operatora, aby w zasadzie wykonać PRAWDZIWĄ FAŁSZ i każdą FAŁSZ PRAWDZIWĄ. więc:

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

EDYCJA: Możesz także sam stworzyć operatora:

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

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

5
Użycie drugiej opcji jest zilustrowane na stronie pomocy (dopasowania) (do której można się dostać po wpisaniu ?"%in%"), gdzie wywoływany jest nowy operator %w/o%.
IRTFM,

23
patrz także ?Negatenp."%ni%" <- Negate("%in%")
baptiste

2
Negate działało dla mnie, gdy zostało użyte po zdefiniowaniu nowego operatora, jak sugeruje baptiste, np. subset(df, variable %ni% c("A", "B"))Ale nie przy bezpośrednim użyciu, np.subset(df, variable Negate("%in%") c("A", "B"))
PatrickT

2
@PatrickT to dlatego, że tylko operatory mogą być używane jako operatory. a operatorzy są albo wbudowani, albo zaczynają i kończą %. Aby utworzyć operator, musisz przypisać funkcję z dwoma operandami do nazwy rozpoczynającej się i kończącej na %.
latające owce


31

Jeśli spojrzysz na kod %in%

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

wtedy powinieneś być w stanie napisać swoją wersję przeciwną. używam

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

Innym sposobem jest:

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

doskonałe rozwiązanie .. Działa, gdy nie udaje się regularne negowanie.
agatha

17

Oto wersja, filterw dplyrktórej zastosowano tę samą technikę, co przyjęta odpowiedź, negując logikę za pomocą!

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

12

Używanie negatez pozwala purrrrównież szybko i starannie wykonać lewę:

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

Zatem użycie to na przykład

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

2
Jest też wbudowany, Negatektóry robi to samo. Jedyną różnicą jest to, że mruczenie wywołuje as_mapperto, co przekazujesz, podczas Negatepołączeń match.fun. rdocumentation.org/packages/purrr/versions/0.2.5/topics/… stat.ethz.ch/R-manual/R-devel/library/base/html/match.fun.html
latające owce

7

purrr::compose() to kolejny szybki sposób na zdefiniowanie tego do późniejszego wykorzystania, jak w:

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

3

Można użyć innego rozwiązania setdiff

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

D2 = setdiff(D1, D0)

D2 jest twoim pożądanym podzbiorem.



0

Myślę, że najczystsze użycie jest po prostu

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

Czym różni się to znacznie od odpowiedzi tutaj zamieszczonych?
camille

0
library(roperators)

1 %ni% 2:10

Chociaż może to być poprawna odpowiedź, byłaby bardziej przydatna z dodatkowym wyjaśnieniem, dlaczego to działa. Rozważ edycję, aby zawierała dalsze szczegóły, a jeśli uważasz, że jest lepsza niż zaakceptowana odpowiedź, która została opublikowana prawie dziesięć lat temu.
Jeremy Caney


-1

Pomoc dla% w% help("%in%")obejmuje w sekcji Przykłady tę definicję braku w,

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

Spróbujmy:

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

Alternatywnie

"%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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.