R中有没有办法在R中写出(a或b)==(c或d)?

11t*_*hal 6 logic boolean r

我想选择 (a 或 b) == (c 或 d) 的行,而不必写出所有组合。例如:

a  b  c  d
1  2  3  4
1  1  2  2
1  2  1  3
2  5  3  2
4  5  5  4
Run Code Online (Sandbox Code Playgroud)

df$equal <- df$a == df$c | df$a == df$d | df$b == df$c | df$b == df$d

会导致:

a  b  c  d equal
1  2  3  4 FALSE
1  1  2  2 FALSE
1  2  1  3 TRUE
2  5  3  2 TRUE
4  5  5  4 TRUE
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以压缩语句,(a 或 b) == (c 或 d),这样就不必写出所有四种组合?我需要这个来应对更多复杂情况,其中有更多的组合。例如,(a或b)==(c或d)==(e或f)==(g或h)

tpe*_*ldt 5

或者,作为@akrun 答案的进一步版本:

df <- data.frame(
  a = c(1L, 1L, 1L, 2L, 4L), 
  b = c(2L, 1L, 2L, 5L, 5L), 
  c = c(3L, 2L, 1L, 3L, 5L), 
  d = c(4L, 2L, 3L, 2L, 4L)
)

cbind(df, equal = sapply(1:nrow(df), \(i) any(df[i, 1:2] %in% df[i, 3:4])))
Run Code Online (Sandbox Code Playgroud)

导致:

  a b c d equal
1 1 2 3 4 FALSE
2 1 1 2 2 FALSE
3 1 2 1 3  TRUE
4 2 5 3 2  TRUE
5 4 5 5 4  TRUE
Run Code Online (Sandbox Code Playgroud)


akr*_*run 4

我们可以选择感兴趣的列并执行==

df$equal <- Reduce(`|`, lapply(df[1:2], \(x) rowSums(df[3:4] == x) > 0))
Run Code Online (Sandbox Code Playgroud)

-输出

> df
  a b c d equal
1 1 2 3 4 FALSE
2 1 1 2 2 FALSE
3 1 2 1 3  TRUE
4 2 5 3 2  TRUE
5 4 5 5 4  TRUE
Run Code Online (Sandbox Code Playgroud)

或者使用if_any

library(dplyr)
df %>%
  mutate(equal = if_any(a:b,  ~.x == c|.x == d))
  a b c d equal
1 1 2 3 4 FALSE
2 1 1 2 2 FALSE
3 1 2 1 3  TRUE
4 2 5 3 2  TRUE
5 4 5 5 4  TRUE
Run Code Online (Sandbox Code Playgroud)

如果列较多且基于'a'、'b'列进行比较

df %>%
    mutate(equal = if_any(-c(a, b), ~ .x == a|.x == b))
Run Code Online (Sandbox Code Playgroud)

数据

df <- structure(list(a = c(1L, 1L, 1L, 2L, 4L), b = c(2L, 1L, 2L, 5L, 
5L), c = c(3L, 2L, 1L, 3L, 5L), d = c(4L, 2L, 3L, 2L, 4L)),
 class = "data.frame", row.names = c(NA, 
-5L))
Run Code Online (Sandbox Code Playgroud)