我正在处理三个实验,我将其存储在三个列表中:exp1
,exp2
和exp3
。每个列表都有多个项目(name
,conditions
,dataset_a
,dataset_b
等。有时我想对所有实验进行操作。有没有办法将它们的名称存储在变量中并动态调用它们?这不起作用:
all_exp <- list(exp1=exp1,exp2=exp2,exp3=exp3)
因为如果我稍后在实验中添加了某些内容,all_exp
会在之前的状态下获得实验的硬拷贝,而不是参考。
这种作品:
all_exp_names <- c("exp1","exp2","exp3")
all_exp <- lapply(all_exp_names, function(exp_name) (eval(parse(text=exp_name))))
但必须有一个更简单的方法,此外,返回的列表会丢失实验名称。
答案 0 :(得分:7)
我想你想要
lapply(all_exp_names,get)
但实际上并没有返回命名列表。你可以做到
setNames(lapply(all_exp_names,get),all_exp_names)
虽然你经常使用它,但你可以把它打包成一个函数(虽然你可以把它打包成一个函数)(请参阅@ JoshOBrien的答案以获得更好的解决方案)。
我认为,更为惯用的事情就是首先将数据的参考副本保存在命名列表中。
编辑:我下面的原始延迟分配/评估代码很聪明,但完全错过了R有一个内置delayedAssign
函数,它做了同样的事情(但可能更强大)作为我的makeDelayVar
功能如下:
delayedAssign("exp_all",list(exp1=exp1,exp2=exp2))
(感谢do.call and curve can not plot a function inside another function environment指出这一点。)如下所示定义中缀运算符%<%
的技巧可能仍然很方便。
<小时/> 如果确实想要延迟分配,这可以(但不是简单地):
makeActiveBinding("all_exp",function() list(exp1=exp1,exp2=exp2), .GlobalEnv)
exp1 <- 2
exp2 <- 3
all_exp
## $exp1
## [1] 2
##
## $exp2
## [1] 3
您也可以将其包装在makeDelayVar
函数中,尽管您可能需要注意评估环境。
makeDelayVar <- function(var,val) {
makeActiveBinding(deparse(substitute(var)), function() val, parent.frame())
}
makeDelayVar(all_exp, list(exp1=exp1,exp2=exp2))
all_exp
此操作与上述相同(您可以删除exp1
和exp2
,定义all_exp
,然后如果要确认此过程,请重新定义exp[12]
真的在做延迟评估)。
为了更加愚蠢,您可以定义%<%
来执行延迟分配(R允许将中缀运算符定义为%[character]%
):
`%<%` <- makeDelayVar
all_exp %<% list(exp1,exp2)
但是,我会谨慎使用它 - 在某些情况下它可能会很脆弱。例如,将它限制在交互式上下文中,如果它中断或者做了一些有趣的事情你就会立即知道,并且不要试图巧妙地将延迟评估的结果作为函数等的参数传递。
答案 1 :(得分:7)
如果您想保留姓名,可以使用sapply(..., simplify=FALSE, USE.NAMES=TRUE)
:
A <- B <- C <- 1:4
nms <- c("A", "B", "C")
sapply(nms, get, simplify=FALSE, USE.NAMES=TRUE)
## $A
## [1] 1 2 3 4
##
## $B
## [1] 1 2 3 4
##
## $C
## [1] 1 2 3 4