Противоположность% в%


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

Ответы:


355

Вы можете использовать !оператор, чтобы в основном сделать любое ИСТИНА ЛОЖЬ и каждую ЛОЖЬ ИСТИНА. так:

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

РЕДАКТИРОВАТЬ: Вы также можете сделать оператор самостоятельно:

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

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

5
Использование второй опции проиллюстрировано на странице справки (соответствия) (куда вы попадете, если вы наберете ?"%in%"), где вызывается оператор new %w/o%.
IRTFM

23
также, см., ?Negateнапример,"%ni%" <- Negate("%in%")
крестить

2
Negate работал для меня, когда он использовался после определения нового оператора, как предлагает Баптист, например 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

Использование negatefrom 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'))

Как это существенно отличается от ответов, уже размещенных здесь?
Камилла

0
library(roperators)

1 %ni% 2:10

Хотя это может быть правильным ответом, было бы более полезно с дополнительным объяснением того, почему это работает. Подумайте о том, чтобы отредактировать его, чтобы включить дополнительную информацию, и если вы считаете, что это лучше, чем принятый ответ, опубликованный почти десять лет назад.
Джереми Кейни


-1

Справка для% in%, 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.