我有两个长列表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")
这是您以可重现形式截取的数据:
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()
连接 A
和 B
中的列表元素,我获得了所需的输出,但必须操作所提供向量的元素,所以我想出了这个:
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
占位符来引用...
的各个元素; ..1
是A
,..2
是B
。当然,foo()
仅适用于两个列表,但不强制执行或进行任何检查,只是为了简单起见。 foo()
还需要处理A
或B
或两者兼而有之的情况character(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
更有意义,但使用基本相同的代码。这是一个直接与A
和B
一起工作的新函数,但我们迭代seq_along()
生成的A
(1, 2, 3, length(A)
)元素的索引:
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"