执行计数器内部功能以检查进度



我有一个函数正在应用于矩阵。但矢量太大了,我想用计数器检查一下它的进展。

N = 10
j = 0
functionX <- function(a,b,c) {
... stuff here ...
j<- j+1
print(paste(j/N,'%'))
}
a <- mapply(functionX, a[1:10,1],b[1:10,2],c[1:10,3])

但这种方法不起作用,因为使用mapply,j永远不会大于1,我希望避免循环。

问题出在functionX内部,您正在为j赋值,因此您还定义了一个新的j变量,该变量仅存在于函数环境中,与functionX外部定义的j不同。

如果你想更改外部j,你可以做:

j <<- j+1

然而,最好不要在父环境中修改变量,所以我建议您将一个新变量传递给mapply,表示迭代计数器,例如:

N = 10
functionX <- function(iteration,a,b,c) {
    # elaboration here
    print(paste( (iteration/N) * 100,'%'))
}
a <- mapply(functionX, 1:10, a[1:10,1],b[1:10,2],c[1:10,3])

写入全局环境从来都不是一个好主意,所以使用一个返回函数的函数。

counter = function(FUN, report=10) {
    j <- 0L                      # initialize the counter
    function(...) {              # a function that takes '...' and...
        j <<- j + 1L             # increment j in a containing env
        if ((j %% report) == 0L)
            message(j)
        FUN(...)                 # ...passes all args '...' to FUN
    }
}

j <<- j + 1行表示,对于赋值,首先查看定义函数的环境,而不是函数本身。线路j <- 0L充当一种切入点,<<-在这里查找j——它在这个环境中找到并更新它。如果未找到j,则<<-运算符将继续在定义环境中寻找符号,直到到达全局环境。

行动中:

> x = sapply(1:20, counter(c, 5))    # concatenate elements c()
5
10
15
20
> x
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
> countedc = counter(c)
> x = integer(); for (i in 1:12) x = countedc(x, i)
10
> for (i in 1:9) x = countedc(x, i)
20
> x
 [1]  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9

也可以使用CCD_ 12。如果FUNsubset()那样使用"非标准评估"作为其参数,则可能会出现问题。

矩阵运算很少需要很长时间;也许您正在迭代,但应该使用矢量化计算?

注意,我定义并命名为j的任何全局变量都将是不变的

> j <- 42   # Yes! the meaning of life. Don't lose this!
> countedc(x, 0)
 [1]  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9  0
> j         # Would have been clobbered if counter used global env
[1] 42

最新更新