2011-06-05 4 views
35

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

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», или «е», я хочу, чтобы избавиться от этой строки наблюдений, производя следующий информационный кадр:

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

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

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%, но это, кажется, не существует. Любые идеи?

ответ

37

! должен быть вокруг внешней высказыванием:

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 
44

Попробуйте

subset(data, !(v1 %in% c("b","d","e"))) 
+0

Приятный и простой, спасибо. Я не уверен, какое решение мне больше нравится, это тот или тот, который предоставил Андри. Они легки и эффективны. Все три решения работают для меня, и я никогда не использовал 'which()' before. Поэтому было приятно познакомиться с этой функцией. – Jota

+9

Если это поможет вам решить, использовать ли 'подмножество' или' [', см. Предупреждение в справке для'? Subset': * «Это функция удобства, предназначенная для интерактивного использования. Для программирования лучше использовать стандартные функции подмножества, такие как [, и, в частности, нестандартная оценка подмножества аргументов может иметь непредвиденные последствия ». * – Andrie

+0

@Andrie Спасибо за добавление разъяснений. – chl

3
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 
4

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

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

Здесь первый тест 1==1 который является значение TRUE, второй 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 (FALSE), потому что левая сторона меньше. Если одна из сторон является только один элемент, то, что повторяется:

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

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

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

> 1:3 == 1 & 1:3 != 2 
[1] TRUE FALSE FALSE 
10

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

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

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

+1

не должны быть '' ', а не' & '? –

+0

@BenBolker Если вы измените на '' ', вы получите те же данные, что и в них. – Jota

+1

@Frank Можете ли вы объяснить логику' & 'в паре с'! = 'Здесь? Как и Бен, похоже, что '' 'следует использовать, но вы правы, что это не должно. Я особенно запутался в подмножестве нескольких столбцов. Например, используя вышеприведенные данные Herman, чтобы удалить все случаи «b» из v1 и все «n» из v2, я бы подумал, что 'my.df [my.df $ v1! =" B "& my. df $ v2! = "n",] 'будет удалять только те случаи, которые удовлетворяли обоим этим критериям (т. е. только Row 3), а не по одному из этих критериев (т.е. как Row 3, так и Row 4). Фактически, использование '|' с '! =' Делает то, что я ожидаю '&', но я не понимаю почему. – coip

5
data <- data[-which(data[,1] %in% c("b","d","e")),] 
+3

', который является злым и даст неожиданные результаты в тех случаях, когда ни одно из значений в векторе, которое нужно сопоставить, находится в исходном векторе. – A5C1D2H2I1M1N2O1R2T1

0
sub.data<-data[ data[,1] != "b" & data[,1] != "d" & data[,1] != "e" , ] 

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

1

А также

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") 

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