R 如何将包含第n个列表元素名称的列添加到列表的每个第n个元素?
说我有R 如何将包含第n个列表元素名称的列添加到列表的每个第n个元素?,r,dplyr,R,Dplyr,说我有 library(dplyr) a <- list(a=tbl_df(cars), b=tbl_df(iris)) 在所有这些评论之后,我想我会写一个答案 为此,您应该使用for循环:它可以快速编码、快速执行、可读且简单明了: for (i in seq_along(a)) a[[i]]$name = names(a)[i] 您可以使用map或mappy或lappy代替for循环。在这种情况下,我认为它的可读性会降低 您还可以使用mutate而不是[来添加列。这将更慢: libr
library(dplyr)
a <- list(a=tbl_df(cars), b=tbl_df(iris))
在所有这些评论之后,我想我会写一个答案 为此,您应该使用
for
循环:它可以快速编码、快速执行、可读且简单明了:
for (i in seq_along(a)) a[[i]]$name = names(a)[i]
您可以使用map
或mappy
或lappy
代替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
对于这样一个简单的操作,
[在所有这些评论之后,我想我会写一个答案
为此,您应该使用for
循环:它可以快速编码、快速执行、可读且简单明了:
for (i in seq_along(a)) a[[i]]$name = names(a)[i]
您可以使用map
或mappy
或lappy
而不是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(cars)
。在For
循环中超级快速:For(i In seq__-on(a))a[[i]]$name=names(a)[i]
@imodata(cars)
是不必要的。数据集
包多年来一直延迟加载数据(大多数其他R包也是如此)当您在一个数据帧内按大量组进行操作时,dplyr
性能会大放异彩。您没有数据帧,而是有一个数据帧列表。dplyr
不适用于列表,因此您需要使用map
或lappy
或其他方法对每个数据帧进行操作,并对自定义的这是一个非常简单的函数。它可能不会更快,因为你所做的很简单。请提供一个可复制的数据集。在你问题的第一个代码部分,添加行数据(cars)
。在for
循环中超级快速:for(i在seq_(a)中)a[[i]]$name=names(a)[i]
@imo数据(cars)
是不必要的。数据集
包多年来一直延迟加载数据(大多数其他R包也是如此)当您在一个数据帧内按大量组进行操作时,dplyr
性能会大放异彩。您没有数据帧,而是有一个数据帧列表。dplyr
不适用于列表,因此您需要使用map
或lappy
或其他方法对每个数据帧进行操作,并对自定义的这是一个非常简单的函数。它可能不会更快,因为你所做的很简单。谢谢。如果你从两个tbl_df()开始,你的答案仍然是正确的对象,但dplyr的速度是您示例中的两倍。我只是指出这一点,因为您提到了使用data.table
之前的转换。谢谢,这是一个很好的观点。我使用tbl_df
对象重新运行基准测试。我无法想象有人会多次执行此操作,因此microsecond基准测试在很大程度上让我觉得毫无意义。增加输入数据的大小,使一次运行需要人类可测量的时间,这更有趣。我强烈同意。除了OP在我第一次提出一个简单循环后的评论外,我根本不会进行基准测试:“我在考虑在每个tbl_df上调用一个mutate,最好使用一个函数而不是一个循环(这不是更快吗?。。。“我可能应该强调的是,区别是微不足道的。@Dambo任何向量化解决方案,在其核心,仍然只是一个简单的循环。区别在于,通常对于向量化解决方案,循环发生在编译的内部代码中,而不是在解释器中执行显式循环(这涉及到对循环的每个步骤进行多层次的语法、解释等)。显然,这种差异主要对大型循环有影响,例如,在大型数据.frame
的行上循环。在这种情况下—(a)没有内部循环可以完成这项工作,(b)循环可能很小(=列表中的表格数)。谢谢。如果从两个tbl_df()开始,您的答案仍然正确对象,但dplyr的速度是您示例中的两倍。我只是指出这一点,因为您提到了使用data.table
之前的转换。谢谢,这是一个很好的观点。我使用tbl_df
对象重新运行基准测试。我无法想象有人会多次执行此操作,因此microsecond基准测试在很大程度上让我觉得毫无意义。增加输入数据的大小,使一次运行需要人类可测量的时间,这更有趣。我强烈同意。除了OP在我第一次提出一个简单循环后的评论外,我根本不会进行基准测试:“我在考虑在每个tbl_df上调用一个mutate,最好使用一个函数而不是一个循环(这不是更快吗?。。。“我可能应该强调的是,区别是微不足道的。@Dambo任何向量化解决方案,在其核心,仍然只是一个简单的循环。区别在于,通常对于向量化解决方案,循环发生在编译的内部代码中,而不是在解释器中执行显式循环(这涉及到对循环的每个步骤进行多层次的语法、解释等)。显然,这种差异主要对大型循环有影响,例如,在大型数据.frame
的行上循环。在这种情况下—(a)没有内部循环可以完成这项工作,(b)循环可能很小(=列表中的表数)。
# 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))