如何动态调用变量?

时间:2013-01-05 17:54:04

标签: r

我正在处理三个实验,我将其存储在三个列表中:exp1exp2exp3。每个列表都有多个项目(nameconditionsdataset_adataset_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))))

但必须有一个更简单的方法,此外,返回的列表会丢失实验名称。

2 个答案:

答案 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

此操作与上述相同(您可以删除exp1exp2,定义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