4

我有两个长列表 A 和 B,它们的长度相同,但包含不同数量的等效元素:
列表 A 可以包含许多元素,这些元素也可以在同一字段中重复出现。
列表 B 要么只包含一个元素,要么包含一个空字段,即“character(0)”。
A 还包含一些空字段,但是对于这些记录,B 中始终存在一个元素,因此 A 和 B 中没有带有空字段的记录。
我想将 A 和 B 的元素组合成一个相同长度的新列表, C、按照以下规则:

  • A 中的所有元素都必须存在于 C 中——包括它们在同一字段中的潜在重复。
  • 如果 B 包含同一记录的 A 中尚不存在的元素,则它也将被添加到 C 中。
  • 但是如果 B 包含一个已经存在于同一记录的 A 中的元素,它将被忽略。
  • 如果 A 有一个空字段,则该记录的 B 中的元素将添加到 C。
  • 如果 B 有一个空字段,则该记录的 A 中的元素将添加到 C。

这是这些列表如何开始的示例:

> A  
 [1] "JAMES" "JAMES"  
 [2] "JOHN" "ROBERT"  
 [3] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID" "WILLIAM"  
 [4] character(0)  
...  
> B  
 [1] "RICHARD"  
 [2] "JOHN"  
 [3] character(0)  
 [4] "CHARLES"  
...  

这是我正在寻找的正确输出:

> C  
 [1] "JAMES" "JAMES" "RICHARD"  
 [2] "JOHN" "ROBERT"  
 [3] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID" "WILLIAM"  
 [4] "CHARLES"  
... 

我试过了,例如:

C <- sapply(mapply(union, A,B), setdiff, character(0))  

但是,不幸的是,这删除了 ​​A 的重复:

> C  
 [1] "JAMES" "RICHARD"  
 [2] "JOHN" "ROBERT"  
 [3] "WILLIAM" "MICHAEL" "DAVID"  
 [4] "CHARLES"  
...  

谁能告诉我,如何组合这两个列表,保留 A 的重复,并实现我想要的输出?

非常感谢您!

更新:机器可读数据:

A <- list(c("JAMES","JAMES"),
          c("JOHN","ROBERT"), 
          c("WILLIAM","MICHAEL","WILLIAM","DAVID","WILLIAM"),  
          character(0))
B <- list("RICHARD","JOHN",character(0),"CHARLES")
4

1 回答 1

7

这是您的数据片段,以可重现的形式:

A <- list(c("JAMES","JAMES"),
          c("JOHN","ROBERT"), 
          c("WILLIAM","MICHAEL","WILLIAM","DAVID","WILLIAM"),  
          character(0))
B <- list("RICHARD","JOHN",character(0),"CHARLES")

你很亲密mapply()。我通过使用c()连接列表元素获得了所需的输出AB但必须操作提供的向量的元素,所以我想出了这个:

foo <- function(...) {
    l1 <- length(..1)
    l2 <- length(..2)
    out <- character(0)
    if(l1 > 0) {
        if(l2 > 0) {
            out <- if(..2 %in% ..1)
                ..1
            else
                c(..1, ..2)
        } else {
            out <-  ..1
        }
    } else {
        out <-  ..2
    }
    out
}

我们可以参考...使用..n占位符的各个元素;..1A..2B。当然,foo()仅适用于两个列表,但不强制执行此操作或进行任何检查,只是为了保持简单。还foo()需要处理我现在认为的A情况。Bcharacter(0)foo()

当我们在mapply()通话中使用它时,我得到:

> mapply(foo, A, B)
[[1]]
[1] "JAMES"   "JAMES"   "RICHARD"

[[2]]
[1] "JOHN"   "ROBERT"

[[3]]
[1] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID"   "WILLIAM"

[[4]]
[1] "CHARLES"

一个lapply()版本可能比摘要更有意义,..n但使用基本相同的代码。这是一个可以直接使用的新函数,AB我们迭代A( 1, 2, 3, length(A)) 的元素的索引,由 生成seq_along()

foo2 <- function(ind, A, B) {
    l1 <- length(A[[ind]])
    l2 <- length(B[[ind]])
    out <- character(0)
    if(l1 > 0) {
        if(l2 > 0) {
            out <- if(B[[ind]] %in% A[[ind]]) {
                A[[ind]]
            } else {
                c(A[[ind]], B[[ind]])
            }
        } else {
            out <- A[[ind]]
        }
    } else {
        out <- B[[ind]]
    }
    out
}

像这样调用:

> lapply(seq_along(A), foo2, A = A, B = B)
[[1]]
[1] "JAMES"   "JAMES"   "RICHARD"

[[2]]
[1] "JOHN"   "ROBERT"

[[3]]
[1] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID"   "WILLIAM"

[[4]]
[1] "CHARLES"
于 2012-06-14T10:14:35.483 回答