如何结合多个条件子集数据帧使用"或quot;?

我在r中有一个data。frame,我想在两个不同的列上尝试两种不同的条件,但我希望这些条件是包容的。因此,我想用“OR”来组合这些条件。当我想要使用“AND”条件时,我曾经成功地使用过下面的语法。

my.data.frame <- data[(data$V1 > 2) & (data$V2 < 4), ]

但是我不知道在上面的句子中如何使用“或”。

674708 次浏览

你要找的是“|”。看到http://cran.r-project.org/doc/manuals/R-intro.html#Logical-vectors

my.data.frame <- data[(data$V1 > 2) | (data$V2 < 4), ]
my.data.frame <- subset(data , V1 > 2 | V2 < 4)

模仿此函数行为的替代解决方案,更适合包含在函数体中:

new.data <- data[ which( data$V1 > 2 | data$V2 < 4) , ]

有些人批评使用which是不必要的,但它确实可以防止NA值返回不需要的结果。等价的(.i。如果没有which,则不返回V1或V2中任何NA的NA行)到上面演示的两个选项:

 new.data <- data[ !is.na(data$V1 | data$V2) & ( data$V1 > 2 | data$V2 < 4)  , ]

注:我要感谢试图修复上面代码中的错误的匿名贡献者,这个修复被版主拒绝了。实际上,当我更正第一个错误时,我注意到了一个额外的错误。检查NA值的条件子句需要是第一个,如果它要按我的意图处理,因为…

> NA & 1
[1] NA
> 0 & NA
[1] FALSE

当使用'&"时,参数的顺序可能很重要。

为了完整起见,我们可以使用运算符[[[:

set.seed(1)
df <- data.frame(v1 = runif(10), v2 = letters[1:10])

几个选项

df[df[1] < 0.5 | df[2] == "g", ]
df[df[[1]] < 0.5 | df[[2]] == "g", ]
df[df["v1"] < 0.5 | df["v2"] == "g", ]

df$name是相当于 df[["name", exact = FALSE]]

使用dplyr:

library(dplyr)
filter(df, v1 < 0.5 | v2 == "g")

使用sqldf:

library(sqldf)
sqldf('SELECT *
FROM df
WHERE v1 < 0.5 OR v2 = "g"')

以上选项的输出:

          v1 v2
1 0.26550866  a
2 0.37212390  b
3 0.20168193  e
4 0.94467527  g
5 0.06178627  j

用于完整性的data.table选项:

library(data.table)
dt <- data.table(V1 = runif(10, 0, 1),
V2 = letters[1:10])


dt[V1 > 0.5 | V2 == "b",]
#>           V1 V2
#> 1: 0.7294220  a
#> 2: 0.9717687  b
#> 3: 0.7177076  c
#> 4: 0.5963838  e
#> 5: 0.5456320  i

reprex包 (v2.0.1)创建于2022-07-10

有关这个有用包的更多信息,请检查链接

如果有人正在寻找一个非常可扩展的解决方案,如果你想要测试相同条件下的多个列,你可以使用ReducerowSums

样本数据

df <- base::expand.grid(x = c(0, 1),
y = c(0, 1),
z = c(0, 1))
df
#>   x y z
#> 1 0 0 0
#> 2 1 0 0
#> 3 0 1 0
#> 4 1 1 0
#> 5 0 0 1
#> 6 1 0 1
#> 7 0 1 1
#> 8 1 1 1

解决方案

它是否包含0?保留除第8行以外的每一行,仅用1填充。

Reduce()中的函数+基本上是一个OR操作符,因为如果它包含任何TRUE值,它的结果就是>0。

## Reduce ---------------------------------------------------
df[Reduce(f = `+`, x = lapply(df, `==`, 0)) > 0, ]
#>   x y z
#> 1 0 0 0
#> 2 1 0 0
#> 3 0 1 0
#> 4 1 1 0
#> 5 0 0 1
#> 6 1 0 1
#> 7 0 1 1


## rowSums --------------------------------------------------
df[rowSums(df == 0) > 0, ]
#>   x y z
#> 1 0 0 0
#> 2 1 0 0
#> 3 0 1 0
#> 4 1 1 0
#> 5 0 0 1
#> 6 1 0 1
#> 7 0 1 1

多个和条件

注意,通过使用*而不是+,你也可以使用Reduce很容易地应用多个AND条件。如果所有情况都是TRUE,则所有逻辑相乘只返回值>0

df[Reduce(`*`, lapply(df, `==`, 0)) > 0, ]
#>   x y z
#> 1 0 0 0