我对R很新,我对tryCatch
的正确用法感到困惑。我的目标是对大型数据集进行预测。如果预测无法适应内存,我想通过拆分数据来解决问题。
现在,我的代码大致如下:
tryCatch({
large_vector = predict(model, large_data_frame)
}, error = function(e) { # I ran out of memory
for (i in seq(from = 1, to = dim(large_data_frame)[1], by = 1000)) {
small_vector = predict(model, large_data_frame[i:(i+step-1), ])
save(small_vector, tmpfile)
}
rm(large_data_frame) # free memory
large_vector = NULL
for (i in seq(from = 1, to = dim(large_data_frame)[1], by = 1000)) {
load(tmpfile)
unlink(tmpfile)
large_vector = c(large_vector, small_vector)
}
})
重点是,如果没有错误发生,large_vector
会按预期填充我的预测。如果发生错误,large_vector
似乎只存在于错误代码的命名空间中 - 这是有道理的,因为我将其声明为函数。出于同样的原因,我收到一条警告,指出large_data_frame
无法删除。
不幸的是,这种行为不是我想要的。我想从我的错误函数中分配变量large_vector
。我认为一种可能性是指定环境并使用assign。因此,我会在我的错误代码中使用以下语句:
rm(large_data_frame, envir = parent.env(environment()))
[...]
assign('large_vector', large_vector, parent.env(environment()))
然而,这个解决方案对我来说似乎相当肮脏。我想知道是否有可能用“干净”的代码实现我的目标?
[编辑] 似乎有些混乱,因为我把上面的代码主要用来说明问题,而不是给出一个有效的例子。这是一个显示命名空间问题的最小示例:
# Example 1 : large_vector fits into memory
rm(large_vector)
tryCatch({
large_vector = rep(5, 1000)
}, error = function(e) {
# do stuff to build the vector
large_vector = rep(3, 1000)
})
print(large_vector) # all 5
# Example 2 : pretend large_vector does not fit into memory; solution using parent environment
rm(large_vector)
tryCatch({
stop(); # simulate error
}, error = function(e) {
# do stuff to build the vector
large_vector = rep(3, 1000)
assign('large_vector', large_vector, parent.env(environment()))
})
print(large_vector) # all 3
# Example 3 : pretend large_vector does not fit into memory; namespace issue
rm(large_vector)
tryCatch({
stop(); # simulate error
}, error = function(e) {
# do stuff to build the vector
large_vector = rep(3, 1000)
})
print(large_vector) # does not exist
答案 0 :(得分:5)
我会做这样的事情:
res <- tryCatch({
large_vector = predict(model, large_data_frame)
}, error = function(e) { # I ran out of memory
ll <- lapply(split(data,seq(1,nrow(large_data_frame),1000)),
function(x)
small_vector = predict(model, x))
return(ll)
})
rm(large_data_frame)
if(is.list(ll))
res <- do.call(rbind,res)
如果耗尽内存,我们的想法是返回预测结果列表。
注意,我不确定这里的结果,因为我们没有可重现的例子。
答案 1 :(得分:3)
编辑:我们再试一次:
您可以使用finally
的{{1}}参数:
tryCatch
这是一个简化版本,可以看到发生了什么:
step<-1000
n<-dim(large_data_frame)[1]
large_vector <- NULL
tryCatch({
large_vector <- predict(model, large_data_frame)
}, error = function(e) { # ran out of memory
for (i in seq(from = 1, to = n, by = step)) {
small_vector <- predict(model, large_data_frame[i:(i+step-1),]) #predict in pieces
save(small_vector,file=paste0("tmpfile",i)) #same pieces
}
rm(large_data_frame) #free memory
},finally={if(is.null(large_vector)){ #if we run out of memory
large_vector<-numeric(n) #make vector
for (i in seq(from = 1, to = n, by = step)){
#collect pieces
load(paste0("tmpfile",i))
large_vector[i:(i+step-1)] <- small_vector
}
}})
EDIT2:关于可能对您有用的范围的另一个提示(尽管可能不是在这种情况下,因为您不想事先声明large_vector<-NULL
rm(y)
tryCatch({
large_vector <- y
}, error = function(e) {# y is not found
print("error")
},finally={if(is.null(large_vector)){
large_vector<-1
}})
> large_vector
[1] 1
):{{1来自R-help:
运营商&lt;&lt; - & - &gt;&gt;通常只用于函数,和 导致搜索通过父环境进行搜索 被分配的变量的定义......
因此,您可以使用上面的示例代码:
large_vector
答案 2 :(得分:0)
以下代码非常自我解释。实际上,问题是错误函数内的任何内容都不会默认应用于父环境。
b = 0
如上所述,这不起作用:
tryCatch(expr = {stop(“error1”)},错误=函数(e){b = 1})
B'/ P>解决方案1:分配给父环境
tryCatch(expr = {stop(“error2”)},error = function(e){assign(x =“b”,value = 2,envir = parent.env(env = environment()))})
B'/ P>解决方案2:最简单(只有在
list
和expr
分配给b时才有效)b = tryCatch(expr = {stop(“error3”)},错误=函数(e){b = 3;返回(b)})
B'/ P>