Row-wise 操作以查看是否有任何列在任何其他列表中

Row-wise operation to see if any columns are in any other list

我有一个小问题tib如下:

  A     B     C     D    
  <chr> <chr> <chr> <chr>
1 X123  X456  K234  V333 
2 X456  Z000  L888  B323 
3 X789  ZZZZ  D345  O999 
4 M111  M111  M111  M111 
.
.
.
(5000 rows)

我还有一个vector如下:

> vec <- c("X123","X456")
> vec
[1] "X123" "X456"

我正在寻找一种方法来搜索,并在 TRUEFALSE 的小标题右侧添加一个逻辑列(例如,有 5000 行),具体取决于关于 tib 中列的任何值是否包含 vec 中的值。我的目标输出如下:

  A     B     C     D      lgl
<chr> <chr> <chr> <chr>  <lgl>
1 X123  X456  K234  V333   TRUE
2 X456  Z000  L888  B323   TRUE
3 X789  ZZZZ  D345  O999   FALSE
4 M111  M111  M111  M111   FALSE

我有以下内容:

> tib %>% 
+   pmap_lgl(~any(..1 %in% vec))
[1]  TRUE  TRUE FALSE FALSE

这得到了我正在寻找的结果,但我对 syntax 有点困惑。

为什么上述方法有效(即使用 ..1),而不是必须使用 ..1..2..3..4?我的理解是 pmap 根据行方向的输入生成一个向量,所以我假设上面的 ..1 表示第 1 行的向量 c("X123","X456","K234","V333"),第 1 行的 c("X456","Z000","L888","B323") #2 等等

最后,我有两个问题:

  1. 如何将这个新的逻辑向量附加到上面的 tib?我没有任何运气:

tib %>% mutate(lgl = pmap_lgl(~any(..1 %in% vec)))

Error in mutate_impl(.data, dots): Evaluation error: argument ".f" is missing, with no default.

  1. 如果我要观察访问每一行中的每一列(例如,"X123" 用于 pmap 中的第一行),我将如何在 purrr 的语法中做到这一点?

保持简单,您可以将基函数 applyany 函数一起使用:

df$lgl <- apply(df, 1, function(x) any(x %in% vec))

中的..1..2指的是参数个数。我们可以将这些与 mutaterowwise 函数一起使用以获得我们想要的结果:

tib %>%
    mutate(lgl = pmap(., ~c(..1, ..2, ..3, ..4) %in% vec)) %>%
    rowwise() %>%
    mutate(lgl = any(unlist(lgl)))

  V1    V2    V3    V4    lgl  
  <chr> <chr> <chr> <chr> <lgl>
1 X123  X456  K234  V333  TRUE 
2 X456  Z000  L888  B323  TRUE 
3 X789  ZZZZ  D345  O999  FALSE
4 M111  M111  M111  M111  FALSE

pmap 的调用使用 . 作为它的第一个参数,这就是我们正在使用的函数。然后我们使用 c(..1, ..2, ..3, ..4) 为每列创建一个值向量。然后我们需要使用 rowwise 来计算每一行的最终逻辑值。

我的答案的前一次迭代会为 vec = c('M111') 返回不正确的结果,现在它正确地执行了:

tib %>%
    mutate(lgl = pmap(., ~c(..1, ..2, ..3, ..4) %in% c('M111'))) %>%
    rowwise() %>%
    mutate(lgl = any(unlist(lgl)))

  V1    V2    V3    V4    lgl  
  <chr> <chr> <chr> <chr> <lgl>
1 X123  X456  K234  V333  FALSE
2 X456  Z000  L888  B323  FALSE
3 X789  ZZZZ  D345  O999  FALSE
4 M111  M111  M111  M111  TRUE 

Here's a link 到该函数的文档,这可能也很有用。

您可以使用 add_columnpmap_lgl 以及辅助函数来获得 tidyverse 类似于 @YOLO 的基础 apply 解决方案的单行代码。

library(tidyverse)

df <- tibble(A = c('X123', 'X456','X789', 'M111'),
             B = c('X456', 'Z000', 'ZZZZ', 'M111'),
             C = c('K234', 'L888', 'D345', 'M111'),
             D = c('V333', 'B323', '0999', 'M111'))


vec <- c('V333', '0999')

check <- function(...) {

  any(c(...) %in% vec)

}

add_column(df, row_check = pmap_lgl(df, check))

# A tibble: 4 x 5
  A     B     C     D     row_check
  <chr> <chr> <chr> <chr> <lgl>    
1 X123  X456  K234  V333  TRUE     
2 X456  Z000  L888  B323  FALSE    
3 X789  ZZZZ  D345  0999  TRUE     
4 M111  M111  M111  M111  FALSE    

在函数中使用 ... 的警告是它将对提供的 tibble 或数据框的所有列进行操作。如果您有其他列,则需要指定函数参数或限制传递给 pmap_lgl

的数据