如何将列表中包含第n个列表元素名称的列添加到列表的每个第n个元素中?

时间:2016-05-18 17:19:13

标签: r dplyr

说我有

library(dplyr)
a <- list(a=tbl_df(cars), b=tbl_df(iris))

如何向列表的每个元素添加一列name,其值是列表中指定元素的名称? 例如,这对于第一个元素

的输出应该如何
Source: local data frame [50 x 3]

   speed  dist  name
   (dbl) (dbl) (chr)
1      4     2     a
2      4    10     a
3      7     4     a
4      7    22     a
5      8    16     a
6      9    10     a
7     10    18     a
8     10    26     a
9     10    34     a
10    11    17     a

1 个答案:

答案 0 :(得分:2)

在所有这些评论之后,我猜我会写一个答案。

您应该使用for循环:它可以快速编写代码,快速执行,可读且直接:

for (i in seq_along(a)) a[[i]]$name = names(a)[i]

您可以使用mapmapplylapply代替for循环。在这种情况下,我认为它的可读性会降低。

您还可以使用mutate代替[来添加列。这会慢一点:

library(microbenchmark)
library(dplyr)
cars_tbl = tbl_df(cars)
mbm = microbenchmark
mbm(
    mutate = {cars_tbl = mutate(cars_tbl, name = 'a')},
    base = {cars_tbl['name'] = 'a'}
)
# Unit: microseconds
#    expr     min       lq      mean  median       uq     max neval cld
#  mutate 240.617 262.4730 293.29001 276.158 299.7255 813.078   100   b
#    base  34.971  42.1935  55.46356  53.407  57.3980 226.932   100  a 

对于这样一个简单的操作,[<-将很难被击败。 data.table可能会更快,但前提是该对象已经是data.table。如果对象是data.frame而不是tbl_df,那么mutate的速度大约是dplyr的两倍。 但这些差异只有几微秒。除非您反复对至少数十万个数据框的列表执行此操作,否则无关紧要

这并不是说dplyr性能不佳 - 当您使用分组操作时,依赖于内置于df = tbl_df(data.frame(x = rep(1, 1e7))) mbm( mutate = {df = mutate(df, name = 'a')}, base = {df['name'] = 'a'} ) # Unit: milliseconds # expr min lq mean median uq max neval cld # mutate 58.08095 59.87531 132.3180 105.22507 207.6439 261.8121 100 a # base 52.09899 53.96386 129.9304 99.96153 203.8581 237.0084 100 a 的NSE,它非常出色。这只是一个简单的基本解决方案最简单,也是最快的简单案例。

如果我们增加足够的数据大小以便花费相当多的时间来执行这些操作(此处为1000万行),差异基本上消失了:

for

使用map循环和[<-进行实施,比较mutate# base for loop for (i in seq_along(a)) { a[[i]]$name = names(a)[i] } # dplyr in for loop for (i in seq_along(a)) { a[[i]] = mutate(a[[i]], name = names(a)[i]) } # dplyr hiding the loop in Map() a = Map(function(x, y) mutate(x, name = y), x = a, y = names(a))

name

我们可以对这些进行基准测试(我做了 - 如果你想要结果,请查看编辑历史记录),但差异小于1毫秒因此它不重要。选择最简单的东西来阅读,书写和理解。

所有这些都伴随着警告,如果您的最终目标是将这些数据框绑定在一起,并且您希望dplyr::bind_rows列查看数据来自哪个列表元素,那么直接在{{1 }}。