2011-06-05 73 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") 

由于&操作由逗号暗示。