合并存储在列表中的数据帧

时间:2013-11-05 17:13:51

标签: r list merge

我有两个清单。列表中的每个组件都是一个数据框。这两个列表是对称的。它们都包含2006 - 2012年的数据框架,仅限于不同的主题。我想将数据框“水平”合并(即第一个列表中的2006年与第二个列表中的2006年之一,依此类推)获取第三个数据框列表。我试图弄清楚如何用lapply做到这一点,但是必须有一些我对这个函数不了解的东西。

你能帮忙吗?

谢谢。

3 个答案:

答案 0 :(得分:3)

此代码中的l3之类的东西,你的意思是?

DT1 = data.frame(A=1:3,B=letters[1:3])
DT2 = data.frame(A=4:5,B=letters[4:5])
l1 = list(DT1,DT2)
DT1 = data.frame(A=1:3,C=letters[7:9])
DT2 = data.frame(A=4:5,C=letters[11:12])
l2 = list(DT1,DT2)

l3 <- vector(mode = "list", length = length(l1))
for ( i in 1:length(l1))
{
l3[[i]]   <- merge(l2[[i]],l1[[i]], by = "A")
}

答案 1 :(得分:1)

也许这样的事情就是你所追求的?

df1 <- data.frame(year = 2006, x = 1:3)
df2 <- data.frame(year = 2007, x = 4:6)
df3 <- data.frame(year = 2006, x = 7:9)
df4 <- data.frame(year = 2007, x = 10:12)

l1 <- list(x2006 = df1, x2007 = df2)
l2 <- list(x2006 = df3, x2007 = df4)

lapply(names(l1), function(x) cbind(l1[[x]], l2[[x]]))
####
[[1]]
  year x year x
1 2006 1 2006 7
2 2006 2 2006 8
3 2006 3 2006 9

[[2]]
  year x year  x
1 2007 4 2007 10
2 2007 5 2007 11
3 2007 6 2007 12

可能还有其他功能比cbind() merge()更合适,但这应该会让您走上正确的道路。这显然假定您已为您的列表命名,并且这些名称在l1l2之间保持一致。

已编辑添加更多内容

有一些关键的假设使这项工作成功。这些假设是:

  1. 您的列表对象有names
  2. 每个列表中的names在列表之间是一致的
  3. 那么,我指的是names是什么?如果您查看我定义l1的位置的代码,您会看到x2006 = df1x2007 = df2。我在该列表中定义了两个对象df1df2,其中有两个名称x2006x2007

    您可以通过询问names()

    来检查列表的名称
    names(l1)
    ####
    [1] "x2006" "x2007"
    

    另一个关键假设是,您可以使用[[函数按名称索引列表中的对象。例如:

    l1[["x2006"]]
    ####
      year x
    1 2006 1
    2 2006 2
    3 2006 3
    

    所以我们对lapply函数的处理是我们迭代l1的名称,定义一个匿名函数,然后使用[[函数来索引两个列表对象l1l2。我们目前正在使用cbind作为函数,但您可以将cbind替换为几乎任何其他函数。

    正如我上面提到的,这假设两个或更多列表对象之间的names是相同的。例如,这不起作用:

    #change the names of the l2 list
    names(l2) <- c("foo", "bar")
    lapply(names(l1), function(x) cbind(l1[[x]], l2[[x]]))
    ####
    Error in data.frame(..., check.names = FALSE) : 
      arguments imply differing number of rows: 3, 0
    

    names但不一定是相同的顺序。这就是[[函数的好处所在。即:

    #Fix names on l2 again
    names(l2) <- c("x2006", "x2007")
    l2reverse <- list(x2007 = df4, x2006 = df3)
    
    all.equal(
      lapply(names(l1), function(x) cbind(l1[[x]], l2[[x]])),  
      lapply(names(l1), function(x) cbind(l1[[x]], l2reverse[[x]]))
    )
    ####
    [1] TRUE
    

答案 2 :(得分:1)

mapply也可能在这里使用。

以下是您可能要求的第三种解释:

一些示例数据:

DT1 <- data.frame(A=1:3, B=letters[1:3])
DT2 <- data.frame(A=4:5, C=letters[4:5])
l1 <- list(DT1,DT2)
DT1 <- data.frame(A=1:3, B=letters[7:9])
DT2 <- data.frame(A=4:5, C=letters[11:12])
l2 = list(DT1,DT2)

mergemapply

mapply(FUN=function(x, y) merge(x, y, by="A"), 
       l1, l2, SIMPLIFY=FALSE)
# [[1]]
#   A B.x B.y
# 1 1   a   g
# 2 2   b   h
# 3 3   c   i
# 
# [[2]]
#   A C.x C.y
# 1 4   d   k
# 2 5   e   l

供参考....

以下是@ Chase对您使用mapply完成的问题的解释:

mapply(cbind, l1, l2, SIMPLIFY=FALSE)
# $x2006
#   year x year x
# 1 2006 1 2006 7
# 2 2006 2 2006 8
# 3 2006 3 2006 9
# 
# $x2007
#   year x year  x
# 1 2007 4 2007 10
# 2 2007 5 2007 11
# 3 2007 6 2007 12

以下是@ Codoremifa对您使用mapply完成的问题的解释:

mapply(FUN=function(x, y) merge(x, y), 
       l1, l2, SIMPLIFY=FALSE)
# [[1]]
#   A B C
# 1 1 a g
# 2 2 b h
# 3 3 c i
# 
# [[2]]
#   A B C
# 1 4 d k
# 2 5 e l

如果你发布一些样本数据和你的预期输出,那么更有帮助的是,你不必猜测你想要做什么: - )