我有一个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。
提前谢谢!
答案 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
})
您可能希望重命名上面的列,而不是取消警告。