通过要删除的行的多个逻辑条件来子集数据帧

时间:2011-06-05 16:28:32

标签: r dataframe subset

我想通过指定要保留在新数据帧中的!)行来对数据帧进行子集化(过滤)。以下是简化的示例数据框:

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 个答案:

答案 0 :(得分:46)

试试这个

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

答案 1 :(得分:39)

!应该在声明的外部:

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

答案 2 :(得分:10)

您还可以通过包含&来分隔语句,将事情分解为单独的逻辑语句来实现此目的。

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

这不优雅,需要更多代码,但对于较新的R用户可能更具可读性。正如上面的评论所指出的,subset是一种“便利”功能,最适合在交互式工作时使用。

答案 3 :(得分:5)

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

答案 4 :(得分: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%',它仅向左矢量化(对于左向量中的每个元素,如果它是其中任何对象的一部分,则对其进行测试)正确的元素)。

或者,您可以使用'&'组合两个逻辑语句。如果两者都为TRUE,则'&'采用两个元素并检查元素:

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

答案 5 :(得分: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

答案 6 :(得分:1)

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

更大但更容易理解(我猜)并且可以与多列一起使用,即使使用!is.na( data[,1])

答案 7 :(得分: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")

由于逗号隐含&运算符。