R 函数编程,子框架内循环的迭代

R 函数编程,子框架内循环的迭代,r,loops,functional-programming,R,Loops,Functional Programming,我想构建一个在循环函数中使用的函数,但是子函数无法从父函数的(1:3中的I)中找到I。我如何避免这个问题?我想可以用赋值(X,envir=sys.frame(which=-1))来解决这个问题,尽管我不知道在这种情况下把它放在哪里或者选择什么帧 #simplified issue parent.fxn = function(X) { for (i in 1:3) child.fxn(X) } child.fxn = function(X) { return(X[i]) }

我想构建一个在循环函数中使用的函数,但是子函数无法从父函数的(1:3中的I)中找到
I
。我如何避免这个问题?我想可以用赋值(X,envir=sys.frame(which=-1))来解决这个问题,尽管我不知道在这种情况下把它放在哪里或者选择什么帧

#simplified issue

parent.fxn = function(X) {
for (i in 1:3)
    child.fxn(X)
}

child.fxn = function(X) {
    return(X[i])
}


#ex. run_script
#parent.fxn(1:10)
#Error in child.fxn(X) : object 'i' not found
作为参考,这里是一个版本的实际脚本,我试图写(以下)。。。我的脚本(下面)中的错误与我的简化示例(上面)略有不同,尽管我不确定原因

library(cluster)
library(data.table)
library(magrittr)

data = data.table(x=runif(300), y=runif(300), z=runif(300))

master.fxn = function(DT, nlvls=3, data.cols=c("x", "y", "z")) {
    Lvls = paste0("Level_", 1:nlvls);
    for (i in 1:nlvls) {
            core.fxn(DT, Lvls, return.k=TRUE)
    }   
}

core.fxn = function(X, mkey, ...) {
    X[, c(mkey[i]):=cluster.fxn(.SD, ...), .SDcols=data.cols, by=c(mkey[0:(i-1)])] %>%
            setkeyv(c(mkey[1:i]))
}

cluster.fxn = function(X, return.ac=FALSE, return.k=FALSE) {
    a = agnes(X, metric="euclidean", method="ward", stand=TRUE)
    if (return.ac) return(a$ac)
    if (return.k) return(cutree(a, k=2))
}

#ex. run_script
#master.fxn(data)
#Error in eval(bysub, parent.frame(), parent.frame()) : object 'i' not found
最后,这里是实际脚本的工作版本,它不使用在循环中使用
[i]
的函数,而是实现了所需的结果。这些脚本被压缩以举例说明错误。如果我能让
core.fxn
master.fxn
循环中工作,那么最终产品中的事情就会简化

library(cluster)
library(data.table)
library(magrittr)

data = data.table(x=runif(300), y=runif(300), z=runif(300))

master.fxn = function(DT, nlvls=3, data.cols=c("x", "y", "z")) {
    Lvls = paste0("Level_", 1:nlvls);
    for (i in 1:nlvls) {
            DT[, c(Lvls[i]):=cluster.fxn(.SD, return.k=TRUE), .SDcols=data.cols, by=c(Lvls[0:(i-1)])] %>%
            setkeyv(c(Lvls[1:i]))
    }   
}

cluster.fxn = function(X, return.ac=FALSE, return.k=FALSE) {
    a = agnes(X, metric="euclidean", method="ward", stand=TRUE)
    if (return.ac) return(a$ac)
    if (return.k) return(cutree(a, k=2))
}

#ex. run_script
#> data
#             x          y         z
#  1: 0.1934689 0.67631296 0.3083592
#  2: 0.5267910 0.93186454 0.9583132
#  3: 0.5533244 0.37712457 0.4022132
#  4: 0.1886627 0.07535931 0.1171205
#  5: 0.7499003 0.90682684 0.6104284
# ---                               
#296: 0.7196245 0.80206991 0.6657839
#297: 0.2453930 0.06807955 0.8126690
#298: 0.3481978 0.23024162 0.4734052
#299: 0.2123976 0.27191432 0.1753336
#300: 0.7312911 0.89491793 0.5417281
#
#>master.fxn(data)
#data[, .SD[1], by=.(Level_1, Level_2, Level_3)]
   #Level_1 Level_2 Level_3         x          y          z
#1:       1       1       1 0.0584953 0.77933040 0.76432541
#2:       1       1       2 0.1814877 0.65263178 0.41425295
#3:       1       2       1 0.9932725 0.99409350 0.96849477
#4:       1       2       2 0.9102010 0.76071068 0.69283525
#5:       2       1       1 0.9040033 0.85361443 0.30636660
#6:       2       1       2 0.8026868 0.08595128 0.43176372
#7:       2       2       1 0.2167962 0.73551203 0.01174373
#8:       2       2       2 0.5592571 0.84508641 0.37382253
#> 

你反对把
i
作为论据吗
child.fxn=function(i,X){return(X[i])}
?我强烈建议您遵循@CPak的建议。这是处理这个问题最有效的方法。