我有两个长列表A和B,它们具有相同的长度,但包含不同数量的等效元素:
列表A可以包含许多元素,这些元素也可以在同一个字段中重复出现
列表B或者只包含一个元素或一个空字段,即“字符(0)”
A还包含一些空字段但是对于这些记录,B中总是存在一个元素,因此A和B中没有空字段的记录。
我想根据以下规则将A和B的元素组合成一个长度相同的新列表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")
答案 0 :(得分: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()
来连接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
配合使用的新功能,但我们会迭代由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"