Вы были близки, но я немного объясню, как работает lapply
(и mclapply
), потому что вы чувствуете, что вы путаете роль x
.Во-первых, это должно работать:
output_varpart <- mclapply(1:3, function(x){
varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
})
Но почему?
Функция lapply
означает: применить функцию (2-й аргумент) ко всем значениям в списке (первый аргумент).Так что lapply(list('Hello', 'World', '!'), print)
сделает
print('Hello')
print('World')
print('!')
и вернет список длины 3 с результатами (возврат print
- это значение, которое было напечатано)
Но довольно часто, нет ни одной функции, которая делает именно то, что вы хотите.Вы всегда можете определить функцию следующим образом:
my_vari_fun <- function(index) {
varipart(spec.list[[index]], env.list[[index]], spat.list[[index]], type = "parametric")
}
Затем вы можете вызвать ее как my_vari_fun(1)
, и совершенно неважно, будет ли аргумент вызываться x
или index
,или что-то другое.Я уверен, что вы поняли.Поэтому следующим шагом будет
output_varpart <- lapply(list(1,2,3), my_vari_part)
Недостатком этого является то, что он занимает несколько строк кода, и мы, вероятно, больше не будем использовать my_vari_fun
.Вот почему мы можем предоставить анонимную функцию, мы просто предоставляем функцию lapply без присвоения ей имени.Мы просто заменим my_vari_fun
на его «значение» (которое оказывается функцией).
Однако вне этой функции x
ничего не значит.Мы могли бы также назвать это любым другим именем.
Нам просто нужно сказать lapply, какие значения вводить: list(1,2,3)
.Или проще как вектор, который lapply
будет преобразовывать: 1:3
Кстати, я только что вставил 3
здесь, но для общего случая вы можете использовать 1:length(spec.list)
, вы простонеобходимо убедиться, что все списки имеют одинаковую длину.
Наконец, я уже говорил о lapply
, но все это работает одинаково для mclapply
.Разница только в этом, mclapply
распространит свою работу на несколько ядер.
Редактирование: отладка
В отладке больше различий между lapply
и mclapply
.Сначала я расскажу о lapply
.
Если в вашем коде, который выполняется внутри lapply
, есть какая-то ошибка, весь lapply
завершится неудачно, и ничего не будет назначено.Из-за этого иногда трудно точно определить, где произошла ошибка, но это можно сделать.Простой обходной путь может заключаться в lapply
только части вашего ввода, чтобы увидеть, где он ломается.
Но R также поставляется с некоторыми инструментами отладки, где выполнение останавливается, как только возникает ошибка.Я считаю recover
наиболее полезным инструментом.
Вы можете установить его с помощью options(error=recover)
, и каждый раз, когда возникает ошибка, он дает вам обратный список функции, которая вызвала ошибку, с помощью которой эта функцияона была вызвана, с помощью которой была вызвана функция, ...
Затем вы можете выбрать число, чтобы исследовать среду, в которой эта функция выполнялась.Когда я пытаюсь эмулировать вашу ошибку, я получаю следующее:
Error in x * w : non-numeric argument to binary operator
Enter a frame number, or 0 to exit
1: source("~/.active-rstudio-document")
2: withVisible(eval(ei, envir))
3: eval(ei, envir)
4: eval(ei, envir)
5: .active-rstudio-document#20: lapply(1:3, function(x) {
varipart(spec.list[[x]], env.list[[x]], spat.list[
6: FUN(X[[i]], ...)
7: .active-rstudio-document#21: varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
8: as.matrix(scalewt(Y, scale = scale))
9: scalewt(Y, scale = scale)
10: apply(df, 2, weighted.mean, w = wt)
11: FUN(newX[, i], ...)
12: weighted.mean.default(newX[, i], ...)
Многие из них являются внутренними функциями от R, и вы можете увидеть, что делает varipart
: он передает вещи нижним функциям, которыепередать его и т. д.
Для наших целей нам нужен номер 6: здесь lapply
вызывает вашу функцию со значением i-th
.
Как только мы введем 6
,мы получаем новое приглашение, которое гласит Browse[1]>
(в некоторых случаях это может быть другое число), и мы находимся в среде, как будто мы только что ввели наш
function(x){
varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
}
Что означает, что x
будетдаст вам значение, для которого эта функция не работает, а spec.list[[x]]
и т. д. сообщит вам, для каких входов varipart
произошел сбой.Тогда последний шаг - решить, что это значит: либо varipart
не работает, либо один из ваших входов.
В этом случае я заметил, что могу получить ту же ошибку, если в одном из столбцов в data.frame
будет что-то другое, чем numeric
.Но вам придется посмотреть, является ли это вашей проблемой, но отладка станет намного проще, если вы выяснили, где проблема.
С mclapply
mclapply
работает на нескольких ядрах, что означает, что в случае ошибки в одном ядре другие ядра по-прежнему завершают свою работу.
Для вычислений, в которых разветвленный процесс обнаружил ошибку, эта ошибка будет возвращаемым значением в виде try-error
-объекта.Но учтите, что так будет и для других итераций того же ядра.Так что если для mclapply(1:10, fun)
, fun(1)
выдает ошибку, в случае 2 ядер, все нечетные входы будут показывать эту ошибку.
Таким образом, мы можем посмотреть на возвращаемое значение, чтобы сузить наш поиск вниз:
sapply(output_varpart, class)
Ошибка (и) - это / и есть в итерациях, где выходной класс равен try-error, но мы не можем точно знать, какой именно.
Как практическирешить это зависит от размера вычислений.
Если они были действительно обширными, возможно, стоило бы сохранить те значения, которые действительно были успешными, и сузить их, повторно запустив только неисправные детали.Или, если я просто вижу один try-error
, нам не нужно больше смотреть.
Но обычно я считаю наиболее полезным изменить mclapply
на обычный lapply
и использовать подход, описанный выше.