2012-06-14 199 views
3

我有两个长的列表A和B,它们具有相同的长度,但包含不同数量的等效元素:
列表A可以包含许多也可以在同一字段中重复的元素。
列表B或者只包含一个元素或者一个空字段,即“字符(0)”。
A也包含一些空字段,但对于这些记录总是有一个元素存在于B中,所以在A和B中没有空字段的记录。
我想将A和B的元素合并到一个新列表中根据以下规则,相同长度C:结合列表元素?

  • 来自A的所有元素必须存在于C中 - 包括它们在同一领域中的潜在复发。
  • 如果B包含一个不在同一记录的A中的元素,它也将被添加到C中。
  • 但是,如果B包含已存在于同一记录的A中的元素,它将被忽略。
  • 如果A具有空字段从乙此记录的元件将被添加到C.
  • 如果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") 
+1

您能否以其他人可以阅读的方式提供数据?这将有助于他们运行示例,他们有更多时间为您找到一个好的解决方案。看看你如何做到这一点:[SO](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)。特别是,看看'dput'。 –

+0

非常感谢您的意见和建议!下次我会尽可能地注意它。 – user0815

回答

7

这里是你的数据snippte,可复制的形式:

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()也需要处理AB或两者都是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更有意义但本质上使用相同的代码。下面是与AB直接工作的新功能,但我们遍历的A1, 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" 
+0

非常感谢您为您的解决方案完美运作!除此之外,感谢您对我的问题的有用编辑/更新。 – user0815