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

Jot*_*ota 37 r subset dataframe

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

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
Run Code Online (Sandbox Code Playgroud)

例如,如果列v1的一行有"b","d"或"e",我想摆脱那一行观察,产生以下数据帧:

v1 v2 v3 v4
a  v  d  c
a  v  d  d
c  k  d  c    
c  r  p  g
Run Code Online (Sandbox Code Playgroud)

我一次成功地基于一个条件进行子集化.例如,在这里我删除v1包含"b"的行:

sub.data <- data[data[ , 1] != "b", ]
Run Code Online (Sandbox Code Playgroud)

但是,我有很多这样的条件,所以一次做一个是不可取的.我没有成功完成以下任务:

sub.data <- data[data[ , 1] != c("b", "d", "e")
Run Code Online (Sandbox Code Playgroud)

要么

sub.data <- subset(data, data[ , 1] != c("b", "d", "e"))
Run Code Online (Sandbox Code Playgroud)

我也试过了其他一些东西,比如!%in%,但似乎并不存在.有任何想法吗?

chl*_*chl 46

试试这个

subset(data, !(v1 %in% c("b","d","e")))
Run Code Online (Sandbox Code Playgroud)

  • 如果它可以帮助你决定是否使用`subset`或`[`,请查看帮助中的警告`?subset`:*"这是一个便于交互使用的便利函数.编程最好使用标准的子集函数,如[,特别是参数子集的非标准评估可能会产生意想不到的后果."* (9认同)

And*_*rie 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
Run Code Online (Sandbox Code Playgroud)


N B*_*wer 10

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

subset(my.df, my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e")
Run Code Online (Sandbox Code Playgroud)

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


Sac*_*amp 5

这个答案更多是为了解释原因,而不是原因。'=='R中的运算符与运算符的向量化方式相同'+'。每个元素将左侧的元素与右侧的元素相匹配。例如:

> 1:3 == 1:3
[1] TRUE TRUE TRUE
Run Code Online (Sandbox Code Playgroud)

在这里,第一个测试为1==1TRUE,第二个2==2和第三个为3==3。注意,由于顺序错误,这将在第一个和第二个元素中返回FALSE:

> 3:1 == 1:3
[1] FALSE  TRUE FALSE
Run Code Online (Sandbox Code Playgroud)

现在,如果一个对象小于另一个对象,则将重复较小的对象,以匹配较大的对象。如果较大对象的大小不是较小对象的大小的乘积,则会收到警告,提示并非所有元素都会重复。例如:

>  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
Run Code Online (Sandbox Code Playgroud)

这里的第一个匹配是1==1,然后是,2==2最后是1==3(FALSE),因为左侧较小。如果侧面之一仅是一个元素,则重复该步骤:

> 1:3 == 1
[1]  TRUE FALSE FALSE
Run Code Online (Sandbox Code Playgroud)

测试元素是否在向量中的正确运算符确实'%in%'仅是矢量化到左元素的(对于左向量中的每个元素,将测试它是否是右元素中任何对象的一部分)。

或者,您可以使用'&'合并两个逻辑语句。'&'接受两个元素并逐个检查是否都为TRUE:

> 1:3 == 1 & 1:3 != 2
[1]  TRUE FALSE FALSE
Run Code Online (Sandbox Code Playgroud)


小智 5

data <- data[-which(data[,1] %in% c("b","d","e")),]
Run Code Online (Sandbox Code Playgroud)

  • `-which`是邪恶的,并且在矢量中没有匹配的值都在源向量中的情况下会产生意想不到的结果. (3认同)