2013-03-08 3 views
4

Я совершенно новичок в R, и я смущен правильным использованием tryCatch. Моя цель - сделать прогноз для большого набора данных. Если предсказания не могут вписаться в память, я хочу обойти проблему, разбив мои данные.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 из моей функции ошибки. Я решил, что одна из возможностей - указать среду и использовать назначение. Таким образом, я бы использовал следующие операторы в моем коде ошибки:

rm(large_data_frame, envir = parent.env(environment())) 
[...] 
assign('large_vector', large_vector, parent.env(environment())) 

Однако это решение кажется довольно грязным для меня. Интересно, есть ли возможность достичь моей цели с помощью «чистого» кода?

[EDIT] Похоже, что возникает некоторая путаница, потому что я поставил вышеприведенный код, чтобы проиллюстрировать проблему, а не приводить рабочий пример. Вот минимальный пример, который показывает проблему пространства имен:

# 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) 

Идея заключается в том, чтобы вернуть список предсказаний результатов, если вы бежите из памяти.

ПРИМЕЧАНИЕ. Я не уверен в этом, потому что у нас нет воспроизводимого примера.

+0

это на самом деле действительно работа! Я попытался вернуть переменные из функции ошибки раньше, однако я пропустил назначение возврата вызова 'tryCatch' переменной (в этом случае' res'). Большое спасибо! – Jenny

+1

@Jenny Обратите внимание, что вы можете использовать deallocate здесь, в блоке finally. 'finally = {rm (large_data_frame)}'. – agstudy

+0

+1, это гораздо приятнее, чем тот, который я пытался сделать в духе оригинального вопроса. И комментарий @ agstudy делает мои ответы небольшими достоинствами бессмысленными :) –

3

EDIT: Давайте попробуем еще раз:

Вы можете использовать finally аргумент 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 
    } 
}}) 

Вот упрощенная версия, чтобы увидеть что происходит:

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 

EDIT2: Еще один совет относительно сферы, которые могут быть полезны для вас (хотя, возможно, не в такой ситуации, как вы не хотите, чтобы объявить large_vector заранее): <<- оператор из R-помощи:

операторы < < - и - >>, как правило, используются только в функциях, и вызвать поиск к сделанному через материнские среды для существующего определения переменной быть назначен ...

Поэтому вы с ульд использовать выше пример кода, как это:

large_vector<-NULL 
rm(y) 
tryCatch({ 
    large_vector <- y 
}, error = function(e) {# y is not found 
    large_vector <<- 1 
    print("error") 
}) 
> large_vector 
[1] 1 
+0

Код предназначался в основном для иллюстрации моей проблемы, поэтому я сказал, что это выглядит примерно так. Извините, это не воспроизводится таким образом. На самом деле ваше решение требует от меня выделить large_vector перед предложением tryCatch, что невозможно из-за ограничений памяти. Кроме того, назначение большого_вектора внутри функции ошибки все равно не будет выполняться (поскольку оно все еще является функцией с собственным пространством имен) – Jenny

+0

Хорошо, хотя проблема была в распределении памяти внутри функции «предсказание», а не при распределении 'large_vector'. Но вы правы в отношении второго пункта, конечно, работа здесь не будет работать. Сожалею. –

+0

@Jenny, я отредактировал свой ответ, чтобы показать другое решение. Хотя ответ @ agstudy более опрятен, так как ему не нужны временные файлы и т. Д., Это может быть полезно в качестве примера аргумента 'finally' в' tryCatch'. –

0

Код, приведенный ниже, является само собой разумеющимся. В самом деле, проблема заключается в том, что что-либо внутри функции ошибки по умолчанию не применяется к родительской среде.

Ь = 0

как объяснено, это не работает:

tryCatch (выражение = {стоп ("Error1")}, ошибка = функция (е) {Ь = 1})
б

РЕШЕНИЕ 1: присвоить родительской среде

tryCatch (выражение = {остановка ("Error2")}, ошибка = функция (е) {присвоить (х = "B", значение = 2, envir = parent.env (ru v = окружающая среда()))})
б

РЕШЕНИЕ 2: самый простой (работает только если вы назначаете б в обоих expr и error)

б = tryCatch (выражение = {стоп («error3»)}, ошибка = функция (е) {Ь = 3; возвращение (б)})
б

Смежные вопросы