我想在 R 中合并多个 OR 和 AND 条件。我认为x1 == 1 | x1 == 2
可以合并为x1 %in% c(1, 2)
.我想知道如何将x1 == 1 | y1 == 1
和x1 == 1 & y1 == 1
合并为更紧凑的R
代码。
x1 <- c(1, 2, 3)
y1 <- c(1, 2, 4)
x1 == 1 | x1 == 2
#> [1] TRUE TRUE FALSE
x1 %in% c(1, 2)
#> [1] TRUE TRUE FALSE
x1 == 1 | y1 == 1
#> [1] TRUE FALSE FALSE
intersect(x1, y1) == 1
#> [1] TRUE FALSE
intersect(x1, y1) == 2
#> [1] FALSE TRUE
intersect(x1, y1) %in% c(1, 2)
#> [1] TRUE TRUE
> x1 == 1 & y1 == 1
[1] TRUE FALSE FALSE
5
2 个回答
2
创建一些数据
看起来不太x1 == 1 | y1 == 1
冗长,让我们创建更多向量:
set.seed(1)
lapply(1:10, \(.) sample(10, 10, replace = TRUE)) |>
setNames(paste0(c("x", "y"), c(1:5, 1:5))) |>
list2env(.GlobalEnv)
ls()
# [1] "x1" "x2" "x3" "x4" "x5" "y1" "y2" "y3" "y4" "y5"
现在写起来确实变得相当乏味:
x1 == 1 | y2 == 1 | x3 == 1 | y4 == 1 | x5 == 1 | y1 == 1 | x2 == 1 | y3 == 1 | x4 == 1 | y5 == 1
# [1] FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE TRUE TRUE
使用数据框
我们使用逐元素逻辑运算符,因此保证向量具有相同的长度。让我们将它们放入数据框中进行比较:
compare <- function(..., op = c("==", "<", ">", ">=", "<=", "!="), compare_with = 1) {
fun = match.fun(match.arg(op))
rowSums(
fun(data.frame(...), compare_with)
) > 0
}
然后我们可以这样做:
compare(x1, y2, x3, y4, x5, y1, x2, y3, x4, y5)
# [1] FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE TRUE TRUE
或者,如果这仍然需要太多的输入,我们可以将向量放入列表中(无论如何这更好),并将其提供给函数:
# Create a list of x1:x5 and y1:y5
l <- mget(ls(pattern = "[xy]\\d"))
compare(l)
# [1] FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE TRUE TRUE
一些测试
==
这也适用于其他运营商。
identical(
compare(x1, y2, x3, y4, x5, y1, x2, y3, x4, y5, op = "==", compare_with = 1),
x1 == 1 | y2 == 1 | x3 == 1 | y4 == 1 | x5 == 1 | y1 == 1 | x2 == 1 | y3 == 1 | x4 == 1 | y5 == 1
)
# [1] TRUE
identical(
compare(x1, y2, x3, y4, x5, y1, x2, y3, x4, y5, op = ">", compare_with = 9),
x1 > 9 | y2 > 9 | x3 > 9 | y4 > 9 | x5 > 9 | y1 > 9 | x2 > 9 | y3 > 9 | x4 > 9 | y5 > 9
)
# [1] TRUE
表现
使用数据框(而不是矩阵)的优点是它只是指向每个向量的指针列表。这意味着不会创建数据副本。此外,数据框支持按元素进行这些比较操作,而无需迭代列(或行),因此即使您的数据非常大,这也应该相当快。
|
1)以下检查 x1[i] 和 y1[i] 均为 1,即 AND。
x1 <- c(1, 2, 3, 1)
y1 <- c(1, 2, 4, 3)
paste(x1, y1) == "1 1"
## [1] TRUE FALSE FALSE FALSE
2)如果我们知道向量由 >= 1 的整数组成,如问题中所示,那么我们可以使用 pmin 和 pmax。请注意,它们具有可选的 na.rm= 参数,可以将其设置为处理 NA。
pmin(x1, y1) == 1 # OR
## [1] TRUE FALSE FALSE TRUE
pmax(x1, y1) == 1 # AND
## [1] TRUE FALSE FALSE FALSE
所有上述内容都很容易推广到 2 个以上的向量。
3)只涉及x1的问题中的表达式可以稍微缩短
x1 %in% 1:2
## [1] TRUE TRUE FALSE TRUE
4)我们可以将 x1 和 y1 的情况视为广义矩阵乘法,其中 * 替换为 ==,+ 替换为 | 之一。或者 & 。在 APL 语言中,这是 =.v 和 =.^ 。 (有关其他实现,请参阅和 blockmodeling::genMatrixMult。)
`%==.|%` <- function(x, y) apply(t(x) == y, 2, any)
`%==.&%` <- function(x, y) apply(t(x) == y, 2, all)
cbind(x1, y1) %==.&% c(1, 1)
## [1] TRUE FALSE FALSE FALSE
cbind(x1, y1) %==.|% c(1, 1)
## [1] TRUE FALSE FALSE TRUE
4
-
我的想法是定义中缀运算符,但如果数据大小合理,我认为
cbind.data.frame(x1, y1)
更好,因为它不会复制数据。
–
-
在 R 中,矩阵乘法是在矩阵上完成的,而不是在数据帧上完成的,因此如果你想保持类比,输入需要是一个矩阵。
– -
我没明白你的意思——也许是因为我不知道 APL。您是说在某些情况下
cbind(x1, y1) %==.&% c(1, 1)
会给出不同的输出吗data.frame(x1, y1) %==.&% c(1, 1)
?或者您是说由于与矩阵乘法在概念上相似而使用矩阵更好?或两者?
– -
尝试
BOD %*% 1:2
其中 BOD 是内置数据框 您会收到错误,因为数据框不能作为矩阵乘法的参数。
–
|
x1 == 1 & y1 == 1
是TRUE FALSE FALSE
而all(c(x1, y1) == 1)
给出输出FALSE
。有什么想法吗?–
–
–
x1*y1 == 1
–
NA
如果发生,请小心,c(1, NA, 4) == 1 | c(1, NA, 4) == 2
与 不同c(1, NA, 4) %in% c(1, 2)
。与 的`%in%`
相关性大于与 的相关性。?match
`==`
–
|