首页 文章

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

提问于
浏览
37

我想通过指定哪些行( ! )保留在新数据帧中来对数据帧进行子集化(过滤) . 这是一个简化的示例数据框:

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 回答

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

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

  • 5

    ! 应该在语句的外部:

    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
    
  • 1

    试试这个

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

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

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

    这不是很优雅,需要更多代码,但对于较新的R用户可能更具可读性 . 正如上面的评论所指出的, subset 是一个"convenience"函数,最适合交互式工作 .

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

    这个答案更多的是解释原因,而不是如何解释 . 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
    
  • 4
    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
    
  • 10

    并且

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

    由于逗号隐含 & 运算符 .

相关问题