微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用with更新函数中的列表不会返回更新的输出

如何解决使用with更新函数中的列表不会返回更新的输出

如何在函数中使用with()(或替代方法),以便在执行函数后更新并返回数据?我知道正在调用数据(在我的情况下,我想在每个时间步长更新的列表中的对象和为此执行的输入参数),正在执行for循环中的命令,但未在更新数据回。为什么会这样呢?我是否缺少有关with()函数内容

我还尝试了within()within.list(),它们在初始化时返回的输出与此列表相同。

#~ input parameters
xPRM <- list()
xPRM$n_ts   <- 4
xPRM$n_yrs  <- 1
xPRM$n_x1   <- 25
xPRM$n_x2   <- 10
xPRM$n_x3   <- 5

set.seed(1)
my_func <- function(X){
        #~ lists to collect data after functions have been executed in each time-step
        list1    <- vector(mode = "list",length = X$n_ts*X$n_yrs)
        list2    <- vector(mode = "list",length = X$n_ts*X$n_yrs)
        # etc.
        
        #~ list for compartments (computations in each time step will be in these compartments)
        comp.1    <- list()
        comp.2    <- list()
        # etc. 
        
        #~ comp.1 initialisation
        comp.1$ts <- rep(0,X$n_x1)                                      
        comp.1$yr <- rep(0,X$n_x1)
        comp.1$v1 <- rnorm(X$n_x1,X$n_x2,X$n_x3)        
        comp.1$v2 <- rep(0,X$n_x1)
        
        with(c(comp.1,X),for(i in 1:n_ts*n_yrs){
                            ts <- i
                            yr <- ceiling(i/n_ts)
                            
                            v1[v1 >= 5]  <- v1[v1 >= 5]^(n_x3/i)    #~ do something 
                            v2[v1 >= 10] <- v2[v1 >= 10] + n_x3*i   #~ do something again 
                            #print(v2)                              #~ will show that the somethings are being done


                            #~Return data at end of time step
                            list1[[i]] <- comp.1
                            # list2[[i]] <- comp.2
                            # etc.
                    }
        )
        all_lists <- list(A = list1,B = list2
                          # etc.,)
        all_lists
        # list1
        # comp.1
}

my_func(X = xPRM)

编辑

可以使用以下代码生成预期输出的示例:

set.seed(1)
#~ lists to collect data after functions have been executed in each time-step
list1    <- vector(mode = "list",length = X$n_ts*X$n_yrs)
list2    <- vector(mode = "list",length = X$n_ts*X$n_yrs)
# etc.

#~ comp.1 initialisation
comp.1$ts <- rep(0,xPRM$n_x1)                                      
comp.1$yr <- rep(0,xPRM$n_x1)
comp.1$v1 <- rnorm(xPRM$n_x1,xPRM$n_x2,xPRM$n_x3)        
comp.1$v2 <- rep(0,xPRM$n_x1)
for(i in 1:xPRM$n_ts*xPRM$n_yrs){
        comp.1$ts <- i
        comp.1$yr <- ceiling(i/xPRM$n_ts)
        
        comp.1$v1[comp.1$v1 >= 5]  <- comp.1$v1[comp.1$v1 >= 5]^(xPRM$n_x3/i)    #~ do something 
        comp.1$v2[comp.1$v1 >= 10] <- comp.1$v2[comp.1$v1 >= 10] + xPRM$n_x3*i   #~ do something again 
        
        #~Return data at end of time step
        list1[[i]] <- comp.1
        # list2[[i]] <- comp.2
        # etc.
}
all_lists <- list(A = list1,B = list2
                  # etc.,)
#~ Expected output
all_lists

解决方法

问题是base R在调用时创建的本地环境中执行其所有操作,包括分配。这意味着df$check <- +( Reduce(`&`,lapply(split.default(replace(df[-1],is.na(df[-1]),0),sub("time_\\d+","",names(df)[-1])),function(x) !(x[[1]] & !x[[2]])))) 不会在with()范围之外进行更新。

来自with() docs

with 是一种通用函数,用于在由数据构造的本地环境中评估expr。
...
请注意,expr中的分配发生在构造的环境中,而不是在用户的工作空间中。
...
对于交互式使用来说,这是非常有效的,而且阅读起来很不错。但是,对于编程(即,在一个人的函数中),需要格外小心,并且通常应避免使用with(),例如,数据中的变量可能会意外覆盖局部变量,请参见参考资料。

您可以坚持使用list1赋值运算符在全局上下文中更新with()。 (请注意,应谨慎使用这种强制全局分配-请参见讨论here。)

此外,list1实际上并未在其自身的<<-上下文中进行更新,因此您需要在完成计算后建立一个列表并将其存储在comp.1

赞:

with()

进行了这些更改后,list1[[i]]实现的输出将与您的预期输出完全匹配。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。