是否有一个与Mathematica的Sow和Reap函数等效的R来构建列表? [英] Is there an R equivalent to Mathematica's Sow and Reap functions for building lists?

查看:150
本文介绍了是否有一个与Mathematica的Sow和Reap函数等效的R来构建列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Mathematica具有有趣的增量构建列表的方式(或更多一张清单),您可以在复杂计算的各个点上计算得出的结果.我想在R中做类似的事情.

Mathematica has an interesting way of incrementally building a list (or more than one list) of results that you calculate at various points of a complicated computation. I'd like to do something similar in R.

在Mathematica中,您可以收集对 函数,将整个计算包装在对 Reap的调用中函数. R是否具有与这些功能等效的功能?您是否可以使用环境和<<-运算符来模拟它,或者作用域规则不允许它?

In Mathematica, you can collect the list of each argument to each invocation of the Sow function during a computation by wrapping the entire calculation in call to the Reap function. Does R have any equivalent to these functions? Could you perhaps emulate it with environments and the <<- operator, or would the scoping rules not permit it?

编辑:这是一个人为的示例.假设我想产生一个立方体的总和,但是我也想收集我用来做立方体之和的数字的平方.我知道可能会有更多惯用的方式来进行这种精确的计算,但这代表在收集沿途产生的各种物品时得到一些最终答案.

Edit: Here's a contrived example. Suppose I want to produce a sum of cubes, but I want to also to collect the squares of the numbers I used to make the sum of cubes. I know there may be more idiomatic ways of doing this exact calculation, but it represents getting some final answer while collecting various items produced along the way.

reap(sum(sapply(1:100, function(i) { sow(squares = i * i); i * i * i }))

我希望它返回的东西是立方体的总和,再加上一个包含正方形列表的命名变量"squares".

I'd want this to return something that has the sum of cubes plus a named variable "squares" containing the list of squares.

推荐答案

我尚未对此进行彻底的测试,但这似乎可以用于您的简单示例.在这里,我们定义reapsow

I haven't thoroughly tested this, but it seems to work for your simple example. Here we define reap and 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()将返回一个列表,该列表具有作为第一个元素传递的表达式的自然"返回值,然后它将添加与sow()调用期间使用的名称相对应的命名元素.因此,如果您运行

So the reap() function basically just defines a new environment and calls it's argument within that context. The sow function takes a named parameters list, and evaluates it's parameters and assigns to the nearest enclosing "reap" environment. Finally, reap() will return a list with the "natural" return value of expression it was passed as the first element, and then it will add named elements corresponding to the names used during the sow() calls. So if you run

reap(sum(sapply(1:5, function(i) { sow(squares=i * i); i * i * i; })))

你得到

[[1]]
[1] 225

$squares
[1]  1  4  9 16 25

正如我提到的,这似乎适用于简单的测试用例.我确信可以对找到并分配给正确的工作收割环境进行改进.但这至少可以为您提供这样的起点.

As I mentioned, this seems to work for the simple test case. I'm sure improvements could be made to finding and assigning to the correct working reaping environment. But this might provide a starting point at least should you wish to pursue something like this.

这篇关于是否有一个与Mathematica的Sow和Reap函数等效的R来构建列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆