Навпаки% у%


262

Категорична змінна V1 у кадрі даних D1 може мати значення, представлені літерами від A до Z. Я хочу створити підмножину D2, яка виключає деякі значення, скажімо, B, N і T. В основному я хочу команду, яка є протилежність %in%

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

66
не в%? ( !(x %in% y)). Життя іноді може бути легким ...
Joris Meys

Відповіді:


354

Ви можете використовувати !оператора, щоб в основному створити будь-яку ІСТИЧНУ ФАЛЬСУ та кожну ЛУЖНУ ІСТИНУ. так:

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

EDIT: Ви також можете зробити оператора самостійно:

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

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

5
Використання другого варіанта проілюстровано на сторінці довідки (матчу) (куди ви потрапили б, якщо ввели ?"%in%"), де викликається новий оператор %w/o%.
IRTFM

23
також дивіться, ?Negateнаприклад,"%ni%" <- Negate("%in%")
baptiste

2
Negate працював на мене при використанні після визначення нового оператора, як запропонував baptiste, наприклад subset(df, variable %ni% c("A", "B")), але не при прямому використанні, наприкладsubset(df, variable Negate("%in%") c("A", "B"))
PatrickT

2
@PatrickT тому, що тільки оператори можуть використовуватися як оператори. і оператори або вбудовані, або починаються і закінчуються %. Щоб створити оператора, вам потрібно призначити функцію з двома операндами імені, починаючи і закінчуючи %.
літаючі вівці


31

Якщо ви подивитеся на код %in%

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

тоді ви повинні мати можливість написати свою версію навпаки. я використовую

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

Ще один спосіб:

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

відмінне рішення .. Він працював, коли регулярне заперечення не вдалося.
Агата

17

Ось версія , яка використовує filterв dplyrтому , що застосовує ту ж техніку, що і загальноприйнятому відповідь заперечуючи логічний з:

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

12

Використання negateз purrrтакож робить трюк швидко і акуратно:

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

Тоді використання, наприклад,

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

2
Є також вбудований, Negateякий робить те саме. Єдина відмінність полягає в тому, що блукає дзвінки as_mapperна річ, яку ви передаєте , а Negateдзвінки match.fun. rdocumentation.org/packages/purrr/versions/0.2.5/topics/… stat.ethz.ch/R-manual/R-devel/library/base/html/match.fun.html
літаючі вівці

7

purrr::compose() це ще один швидкий спосіб визначити це для подальшого використання, як у:

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

3

Іншим рішенням може бути використання setdiff

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

D2 = setdiff(D1, D0)

D2 - це бажаний підмножина.



0

Я думаю, що найясніше використання - це просто

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

Чим це суттєво відрізняється від відповідей, вже розміщених тут?
camille

0
library(roperators)

1 %ni% 2:10

Хоча це може бути правильною відповіддю, було б корисніше з додатковим поясненням, чому це працює. Спробуйте відредагувати його, щоб включити додаткові деталі, і якщо ви вважаєте, що це краще, ніж прийнята відповідь, розміщена майже десять років тому.
Джеремі Кейні


-1

Довідка для% у%, help("%in%")включає в розділі Приклади це визначення не в,

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

Давайте спробуємо:

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

Як варіант

"%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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.