两个列表与多列data.frames的条件匹配

时间:2013-06-19 18:37:00

标签: r list dataframe

我有一个data.frames列表,每个data.frames都有多列。每个data.frame都具有相同的结构。 另外我有另一个包含多个data.frames的列表。

让我们说这是两个列表:

firstlist <- list(a=data.frame(AA=5:1,
                        BB=1:5),
           b=data.frame(AA=5:1,
                        BB=1:5),
           c=data.frame(AA=5:1,
                        BB=1:5))
secondlist <- list(a=data.frame(AA=1:10,
                        BB=c(0,0,1,0,0,1,1,0,0,0)),
           b=data.frame(AA=1:10,
                        BB=c(0,1,0,0,0,0,1,0,0,0)),
           c=data.frame(AA=1:10,
                        BB=c(1,0,0,0,0,1,1,0,0,0)))

现在我想将列CC添加到firstlist中的所有data.frames,并相应地填充第二列表中BB列中的值。

问题是:我需要检查第一个列表中AA或BB中的行是否包含第二个列表中AA的值,并将第一个列表中的新列CC填入第二个列表中的BB值。

以上示例数据的预期结果是:

> firstlist
$a
     AA BB CC
  1  5  1  0
  2  4  2  0
  3  3  3  1
  4  2  4  0
  5  1  5  0

$b
    AA BB CC
  1  5  1  0
  2  4  2  1
  3  3  3  0
  4  2  4  1
  5  1  5  0

$c
    AA BB CC
  1  5  1  1
  2  4  2  0
  3  3  3  0
  4  2  4  0
  5  1  5  1

我是否需要使用For循环或有其他方法吗?

更新: 有关所有数据类型,请参阅Thell's solution以获取boolen数据和eddie's solution

提前谢谢!

3 个答案:

答案 0 :(得分:2)

这是另一种相对较短的方式(假设BB中的secondlist是二进制的(只有0和另一个值):

lapply(seq_along(firstlist), function(ix) {
    tt <- secondlist[[ix]][secondlist[[ix]]$BB != 0, ]
    transform(firstlist[[ix]], CC = 1 * (firstlist[[ix]]$AA %in% tt$AA | 
        firstlist[[ix]]$BB %in% tt$AA))
})

答案 1 :(得分:2)

如果CC是真正的布尔值......

f <- function(a,b) cbind( a, CC=b$BB[ match( a$AA, b$AA ) ] |
                                b$BB[ match( a$BB, b$AA ) ]   )
mapply( f, firstlist, secondlist, SIMPLIFY=F )

直接,快速,保持名字......

示例vs lapply版本的基准::

Unit: milliseconds
          expr       min       lq   median       uq      max neval
   this mapply  1.726471 1.840671 1.870504 1.939473 13.88875   100
 Arun's lapply  2.930061 3.048110 3.134402 3.209786 14.61630   100

答案 2 :(得分:1)

lapply(seq_along(firstlist),
       function(i) {
         d.1 = merge(firstlist[[i]], secondlist[[i]], by = "AA", sort = FALSE)
         names(d.1) = c("AA", "BB", "CC")
         d.2 = suppressWarnings(merge(firstlist[[i]], secondlist[[i]], by.x = "BB", by.y = "AA", sort = FALSE))
         names(d.2) = c("BB", "AA", "CC")
         d.1$CC = 0 + (d.1$CC | d.2$CC)
         d.1
       })

您可能希望重命名上面的列,而不是取消警告。