Mathematica有一个interesting way of incrementally building a list(或多个列表)的结果,您可以在复杂计算的各个点进行计算。我想在R中做类似的事情。
在Mathematica中,您可以通过将整个计算包含在Sow
函数的调用中来收集计算期间每次调用Reap
函数的每个参数的列表。 R是否具有这些功能的等价物?您是否可以使用环境和<<-
运算符来模拟它,或者范围规则是否允许它?
修改:这是一个人为的例子。假设我想生成一个多维数据集的总和,但我还想收集我用来制作多维数据集总和的数字的平方。我知道可能有更多惯用的方法来进行这种精确的计算,但它代表了在收集沿途产生的各种物品时获得最终答案。
reap(sum(sapply(1:100, function(i) { sow(squares = i * i); i * i * i }))
我希望这会返回一些具有多维数据集加上一个命名变量&#34; square&#34;包含正方形列表。
答案 0 :(得分:6)
我还没有对此进行过彻底的测试,但它似乎适用于您的简单示例。在这里,我们定义reap
和sow
reap <- function(...) {
expr <- substitute(...)
REAPENV <- new.env()
parent.env(REAPENV) <- parent.frame()
x <- eval(expr, REAPENV)
c(list(x), as.list(REAPENV))
}
sow <- function(...) {
expr <- substitute(alist(...))[-1]
for( f in rev(sys.frames())) {
if(exists("REAPENV", envir=f)) {
re <- get("REAPENV", envir=f)
if (is.null(names(expr))) {
names(expr) <- if(length(expr)==1) {"sow"} else {letters[1:length(expr)]}
}
stopifnot(all(nchar(names(expr))!=0))
for(n in names(expr)) {
sx <- eval(expr[[n]], parent.frame())
cv <- if(exists(n, envir=re, inherits=FALSE)) {get(n, envir=re)} else {list()}
if(length(cv)>0) {
assign(n, append(cv, sx), envir=re)
} else {
assign(n, sx, envir=re)
}
}
break;
}
}
invisible(NULL)
}
因此reap()
函数基本上只定义一个新环境并在该上下文中调用它的参数。 sow
函数接受命名参数列表,并评估它的参数并分配到最近的封闭“reap”环境。最后,reap()
将返回一个列表,其中包含作为第一个元素传递的表达式的“自然”返回值,然后它将添加与sow()
调用期间使用的名称对应的命名元素。所以,如果你运行
reap(sum(sapply(1:5, function(i) { sow(squares=i * i); i * i * i; })))
你得到了
[[1]]
[1] 225
$squares
[1] 1 4 9 16 25
正如我所提到的,这似乎适用于简单的测试用例。我确信可以改进寻找和分配正确的工作收割环境。但这至少可以提供一个起点,如果你想追求这样的事情。