我在r中有一个data。frame,我想在两个不同的列上尝试两种不同的条件,但我希望这些条件是包容的。因此,我想用“OR”来组合这些条件。当我想要使用“AND”条件时,我曾经成功地使用过下面的语法。
my.data.frame <- data[(data$V1 > 2) & (data$V2 < 4), ]
但是我不知道在上面的句子中如何使用“或”。
你要找的是“|”。看到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行)到上面演示的两个选项:
which
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:
dplyr
library(dplyr) filter(df, v1 < 0.5 | v2 == "g")
使用sqldf:
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选项:
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
有关这个有用包的更多信息,请检查链接。
如果有人正在寻找一个非常可扩展的解决方案,如果你想要测试相同条件下的多个列,你可以使用Reduce或rowSums。
Reduce
rowSums
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()
## 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。
*
+
AND
TRUE
>0
df[Reduce(`*`, lapply(df, `==`, 0)) > 0, ] #> x y z #> 1 0 0 0