2011-06-05 52 views
35

的多個邏輯條件我想通過指定!),以保持在新的數據幀的行到子集(過濾器)一數據幀。這裏是一個簡化的樣本數據幀:子集數據幀按行以除去

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%,但似乎並不存在。 有什麼建議嗎?

回答

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()'。所以,很高興能夠介紹這個功能。 – Jota 2011-06-05 17:25:53

+9

如果它可以幫助你決定是使用'subset'還是''',看看'subset'的幫助中的警告:*「這是一個交互式使用的方便函數。對於編程,最好使用標準的子集函數,特別是參數子集的非標準評估可能會有意想不到的後果。「* – Andrie 2011-06-06 12:45:11

+0

@Andrie感謝您加入澄清。 – chl 2011-06-06 12:55:42

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%'其僅矢量向左元件(每個元件在如果它是右元素中的任何對象的一部分,則測試左向量)。可以使用'&'來組合兩個邏輯語句。 '&'需要兩個元素和檢查的elementwise如果都是TRUE:

> 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

不應該是'|'而不是'&'? – 2014-04-09 13:08:12

+0

@BenBolker如果您更改爲'|',您將獲得與輸入相同的數據。 – Jota 2014-07-04 15:10:59

+1

@Frank您可以在這裏解釋'&'與'!='配對的邏輯嗎?像本,似乎應該使用'|',但你說得對,它不應該。我特別困惑於以這種方式對多列進行子集化。例如,使用Herman的上面的示例數據,要從v1中刪除所有「b」的情況,並從v2中刪除所有「n」,我會認爲'my.df [my.df $ v1!=「b」&my。 df $ v2!=「n」,]'只會移除滿足這兩個條件(即只有第3行)的案例,而不是那些條件(即第3行和第4行)。實際上,在'!='中使用'|'並不符合我所期望的','但我不明白爲什麼。 – coip 2015-02-12 16:45:00

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

' - 這是邪惡的,並且在向量中沒有匹配的值在源向量中的情況下會產生意想不到的結果。 – A5C1D2H2I1M1N2O1R2T1 2014-02-01 18:24:56

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

由於&操作由逗號暗示。