【问题标题】:Merging data frames stored in lists合并存储在列表中的数据帧
【发布时间】:2013-11-16 16:05:39
【问题描述】:

我有两个列表。列表中的每个组件都是一个数据框。这两个列表是对称的。它们都包含 2006-2012 年的数据框,只是主题不同。我想“水平”合并数据框(即第一个列表中的 2006 年与第二个列表中的 2006 年的数据框,依此类推)获得第三个数据框列表。我试图弄清楚如何用 lapply 做到这一点,但该功能一定有我不明白的地方。

你能帮忙吗?

谢谢。

【问题讨论】:

  • 没有例子很难理解你想要什么。推荐从这里开始:stackoverflow.com/questions/5963269/…
  • 也许你需要do.call(cbind, List_of_data_frames),但如果没有reproducible example,就很难弄清楚你真正需要什么。
  • 如果你想弄清楚你不明白的地方,最好把不适合你的代码贴出来。
  • 对不起,我很困惑,以至于我没有设法上传一段对我有意义的代码。我觉得这个操作是可能的,因为我真的不知道怎么做。我是初学者,需要完全弄清楚如何使用列表以及适用于它们的功能。下次我会努力的

标签: r list merge


【解决方案1】:

你的意思是,这段代码中的 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")
}

【讨论】:

  • 是的,完全正确。我也想到了一个 for 循环,但我认为使用 lapply 也可以(并且可能更有效)完成这项工作。人们在处理列表时总是建议这样做。不过谢谢!我会听从你的建议。
  • 还有@Riccardo,如果这确实回答了您的问题,那么请考虑单击答案旁边的复选标记以认为它已被接受。
  • 一般apply 和类似的函数比for 循环更有效。在这种情况下,它可能无关紧要。有关如何使 for 循环尽可能高效的更多详细信息和提示,请参阅第 46 页 this issue of R News
  • @Christopher 非常感谢您指定这一点。
  • 这不运行...Error in vector(mode = "list", length = length(l)) : object 'l' not found
【解决方案2】:

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

如果您发布一些示例数据和您的预期输出会更有帮助,这样您就可以减少对您要做什么的猜测:-)

【讨论】:

  • 哇@Ananda Mahto,很好的例子! mapply 的第一个例子就是我要找的那个。下次使用列表时,我会将其用作宝贵的参考。非常感谢。
【解决方案3】:

也许这就是你所追求的?

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在列表之间是一致的

那么,我指的是什么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 的名称,定义一个匿名函数,然后使用[[ 函数来索引两个列表对象@987654343 @ 和 l2。我们目前使用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

【讨论】:

  • 这正是我想要的。你能解释一下你是如何使用 lapply 的吗?在一本非常好的编程手册中,我找到了一个与您类似的示例,但没能理解它。
  • @Riccardo - 为您添加了更多上下文和解释。
  • 非常感谢您抽出时间为我和其他用户留下清晰的解释。多亏了像您这样的人,论坛才成为强大的学习工具。我希望我的声望超过 15 以给你一个 +1。谢谢。
猜你喜欢
  • 2017-09-26
  • 1970-01-01
  • 2017-11-19
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多