如何更优雅地操作不同列表中的 data.frame 对象?

Posted

技术标签:

【中文标题】如何更优雅地操作不同列表中的 data.frame 对象?【英文标题】:How to manipulate data.frame object in different list more elegantly? 【发布时间】:2016-10-11 19:45:40 【问题描述】:

我在列表中有 data.frame 对象,这是我实现的函数的输出。但是,我打算创建一个新列表,将不同列表中的 data.frame 对象放在一起。我尝试了几种方法来获得预期的输出,但并不优雅。有谁知道有效地进行这种操作的任何有用技巧?是否有任何优雅的解决方案来完成这项任务?有什么想法吗?

这是一个小例子:

savedList <- list(
  foo_saved = data.frame(v1=c(1,6,16), v2=c(4,12,23)),
  bar_saved = data.frame(v1=c(7,19,31), v2=c(16,28,41)),
  cat_saved = data.frame(v1=c(5,13,26), v2=c(11,21,42))
)

dropedList <- list(
  foo_droped = data.frame(v1=c(4,9,20), v2=c(7,15,29)),
  bar_droped = data.frame(v1=c(14,26,35), v2=c(21,30,47)),
  cat_droped = data.frame(v1=c(18,29,39), v2=c(25,36,48))
)

这是我的预期输出:

foo <- list(
  foo_saved = data.frame(v1=c(1,6,16), v2=c(4,12,23)),
  foo_droped = data.frame(v1=c(4,9,20), v2=c(7,15,29))
)

bar <- list(
  bar_saved = data.frame(v1=c(7,19,31), v2=c(16,28,41)),
  bar_droped = data.frame(v1=c(14,26,35), v2=c(21,30,47))
)

cat <- list(
  cat_saved = data.frame(v1=c(5,13,26), v2=c(11,21,42)),
  cat_droped = data.frame(v1=c(18,29,39), v2=c(25,36,48))

)

我尝试了一些现有的解决方案,但我对此并不满意。如何轻松获得所需的输出?是否有任何有效、兼容的解决方案?非常感谢

【问题讨论】:

purrr::transpose(list(saved=savedList, droped=dropedList)) 可能是一个选项。 @lukeA:谢谢,这个也很好用。 【参考方案1】:

您可以合并这两个列表,然后拆分名称的共同部分。 split() 不是有史以来最高效的函数,但其​​代码非常简单。

x <- c(savedList, dropedList)
split(x, sub("_.*", "", names(x)))

这给出了以下内容:

List of 3
 $ bar:List of 2
  ..$ bar_saved :'data.frame':  3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 7 19 31
  .. ..$ v2: num [1:3] 16 28 41
  ..$ bar_droped:'data.frame':  3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 14 26 35
  .. ..$ v2: num [1:3] 21 30 47
 $ cat:List of 2
  ..$ cat_saved :'data.frame':  3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 5 13 26
  .. ..$ v2: num [1:3] 11 21 42
  ..$ cat_droped:'data.frame':  3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 18 29 39
  .. ..$ v2: num [1:3] 25 36 48
 $ foo:List of 2
  ..$ foo_saved :'data.frame':  3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 1 6 16
  .. ..$ v2: num [1:3] 4 12 23
  ..$ foo_droped:'data.frame':  3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 4 9 20
  .. ..$ v2: num [1:3] 7 15 29

【讨论】:

我知道你会讨厌它,但这很好:c(savedList, dropedList) %&gt;% split(substr(names(.), 1, 3)) 我个人不太喜欢合并列表和分组。你的解决方案很有趣,我试试看。 @Andy.Jian - split(x, sub("_.*", "", names(x)))[c("foo", "bar", "cat")]? 如果您根据原始列表中的名称订购,您可以使用[sub("_.*", "", names(savedList))] 代替上面的[c("foo", "bar", "cat")] 是的,这正是我想要的。感谢您的大力帮助:)【参考方案2】:

您可以为此使用mapply,它将遍历两个列表并为每对项目创建一个列表:

res <- mapply( list, savedList, dropedList, SIMPLIFY = F)
str(res)
List of 3
 $ foo_saved:List of 2
  ..$ :'data.frame':    3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 1 6 16
  .. ..$ v2: num [1:3] 4 12 23
  ..$ :'data.frame':    3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 4 9 20
  .. ..$ v2: num [1:3] 7 15 29
 $ bar_saved:List of 2
  ..$ :'data.frame':    3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 7 19 31
  .. ..$ v2: num [1:3] 16 28 41
  ..$ :'data.frame':    3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 14 26 35
  .. ..$ v2: num [1:3] 21 30 47
 $ cat_saved:List of 2
  ..$ :'data.frame':    3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 5 13 26
  .. ..$ v2: num [1:3] 11 21 42
  ..$ :'data.frame':    3 obs. of  2 variables:
  .. ..$ v1: num [1:3] 18 29 39
  .. ..$ v2: num [1:3] 25 36 48

【讨论】:

mapplySIMPLIFY = FALSEMap 谢谢。新获得的列表现在变成了嵌套列表,我怎样才能得到嵌套列表呢?我有兴趣为每个子列表做进一步的操作吗?有什么想法吗? 请记住,此解决方案取决于两个列表中元素的一对一顺序。 是的,这个不错。谢谢你的帮助。我宁愿接受使用 Rich 的解决方案。

以上是关于如何更优雅地操作不同列表中的 data.frame 对象?的主要内容,如果未能解决你的问题,请参考以下文章

根据存储在 data.frame 中的单独字符向量,有条件地重命名列表中的列

如何更有效地将嵌套列表扁平化为一个列表而不是使用 unlist 方法?

如何从 r 中的 data.frame 列创建 html 文本条目列表(没有循环)?

一种更优雅书写Python代码的方式

如何优雅地对熊猫中的一系列列表进行热编码[重复]

R循环使用列表中的data.frame的函数