Подмножество фрейма данных несколькими логическими условиями удаляемых строк - PullRequest
37 голосов
/ 05 июня 2011

Я бы хотел установить (отфильтровать) подкадр данных, указав, какие строки не (!) следует хранить в новом фрейме. Вот упрощенный пример кадра данных:

data
v1 v2 v3 v4
a  v  d  c
a  v  d  d
b  n  p  g
b  d  d  h    
c  k  d  c    
c  r  p  g
d  v  d  x
d  v  d  c
e  v  d  b
e  v  d  c

Например, если в строке столбца v1 есть «b», «d» или «e», я хочу избавиться от этого ряда наблюдений, создав следующий кадр данных:

v1 v2 v3 v4
a  v  d  c
a  v  d  d
c  k  d  c    
c  r  p  g

Я успешно выполнил поднабор по одному условию за раз. Например, здесь я удаляю строки, где v1 содержит «b»:

sub.data <- data[data[ , 1] != "b", ]

Однако у меня много таких условий, поэтому делать это по одному не желательно. Я не был успешным со следующим:

sub.data <- data[data[ , 1] != c("b", "d", "e")

или

sub.data <- subset(data, data[ , 1] != c("b", "d", "e"))

Я пробовал и другие вещи, такие как !%in%, но этого, похоже, не существует. Есть идеи?

Ответы [ 8 ]

46 голосов
/ 05 июня 2011

Попробуйте это

subset(data, !(v1 %in% c("b","d","e")))
39 голосов
/ 05 июня 2011

! должно быть за пределами утверждения:

data[!(data$v1 %in% c("b", "d", "e")), ]

  v1 v2 v3 v4
1  a  v  d  c
2  a  v  d  d
5  c  k  d  c
6  c  r  p  g
10 голосов
/ 08 декабря 2011

Вы также можете сделать это, разбив вещи на отдельные логические операторы, добавив & для разделения операторов.

subset(my.df, my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e")

Это не элегантно и требует больше кода, но может быть более читабельным для новых пользователей R. Как указано в комментарии выше, subset - это удобная функция, которая лучше всего используется при интерактивной работе.

5 голосов
/ 04 сентября 2012
data <- data[-which(data[,1] %in% c("b","d","e")),]
4 голосов
/ 05 июня 2011

Этот ответ больше предназначен для объяснения почему, а не как. Оператор '==' в R векторизован так же, как оператор '+'. Он сопоставляет элементы того, что находится слева, с элементами того, что находится справа, для каждого элемента. Например:

> 1:3 == 1:3
[1] TRUE TRUE TRUE

Здесь первый тест 1==1, который ИСТИНА, второй 2==2 и третий 3==3. Обратите внимание, что это возвращает FALSE в первом и втором элементе, потому что порядок неправильный:

> 3:1 == 1:3
[1] FALSE  TRUE FALSE

Теперь, если один объект меньше другого объекта, то меньший объект повторяется столько раз, сколько требуется, чтобы соответствовать большему объекту. Если размер большего объекта не является умножением на размер меньшего объекта, вы получите предупреждение о том, что не все элементы повторяются. Например:

>  1:2 == 1:3
[1]  TRUE  TRUE FALSE
Warning message:
In 1:2 == 1:3 :
  longer object length is not a multiple of shorter object length

Здесь первое совпадение 1==1, затем 2==2 и, наконец, 1==3 (ЛОЖЬ), потому что левая сторона меньше. Если одна из сторон является только одним элементом, то это повторяется:

> 1:3 == 1
[1]  TRUE FALSE FALSE

Правильный оператор для проверки, находится ли элемент в векторе, действительно '%in%', который векторизован только для левого элемента (для каждого элемента в левом векторе он проверяется, является ли он частью какого-либо объекта в правом элементе ).

В качестве альтернативы, вы можете использовать '&' для объединения двух логических операторов. '&' берет два элемента и поэлементно проверяет, являются ли оба ИСТИНАМИ:

> 1:3 == 1 & 1:3 != 2
[1]  TRUE FALSE FALSE
3 голосов
/ 05 июня 2011
my.df <- read.table(textConnection("
v1 v2 v3 v4
a  v  d  c
a  v  d  d
b  n  p  g
b  d  d  h    
c  k  d  c    
c  r  p  g
d  v  d  x
d  v  d  c
e  v  d  b
e  v  d  c"), header = TRUE)

my.df[which(my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e" ), ]

  v1 v2 v3 v4
1  a  v  d  c
2  a  v  d  d
5  c  k  d  c
6  c  r  p  g
1 голос
/ 22 февраля 2018

А также

library(dplyr)
data %>% filter(!v1 %in% c("b", "d", "e"))

или

data %>% filter(v1 != "b" & v1 != "d" & v1 != "e")

или

data %>% filter(v1 != "b", v1 != "d", v1 != "e")

Поскольку оператор & подразумевается запятой.

1 голос
/ 10 сентября 2014
sub.data<-data[ data[,1] != "b"  & data[,1] != "d" & data[,1] != "e" , ]

Больший, но простой для понимания (я думаю) и может использоваться с несколькими столбцами, даже с !is.na( data[,1]).

...