Зацикливание нескольких перечисленных фреймов данных в одну функцию - PullRequest
0 голосов
/ 13 декабря 2018

Я пытаюсь выполнить функцию varipart () из пакета ade4.Я пытаюсь использовать один и тот же номер кадра данных из каждого списка в разных частях одной и той же функции.Мне нужно передать это для каждого набора данных.

########### DATA BELOW
    d1 <- data.frame(y1 = c(1, 2, 3), y2 = c(4, 5, 6))
      d2 <- data.frame(y1 = c(3, 2, 1), y2 = c(6, 5, 4))
      d3 <- data.frame(y1 = c(2, 1, 2), y2 = c(5, 6, 4))
      spec.list <- list(d1, d2, d3)

      d1 <- data.frame(y1 = c(20, 87, 39), y2 = c(46, 51, 8))
      d2 <- data.frame(y1 = c(30, 21, 12), y2 = c(61, 51, 33))
      d3 <- data.frame(y1 = c(2, 11, 14), y2 = c(52, 16, 1))
      env.list <- list(d1, d2, d3)

      d1 <- data.frame(y1 = c(0.15, 0.1, 0.9), y2 = c(0.46, 0.51, 0.82))
      d2 <- data.frame(y1 = c(0.13, 0.31, 0.9), y2 = c(0.11, 0.51, 0.38))
      d3 <- data.frame(y1 = c(0.52, 0.11, 0.14), y2 = c(0.52, 0.36, 0.11))
      spat.list <- list(d1, d2, d3)
###############
      # I have tried two ways 
      library(parallel)
      library(ade4)

        output_varpart <- mclapply(spec.list, function(x){
          varipart(x, env.list, spat.list, type = "parametric")
        })

        output_varpart <- mclapply(x, function(x){
          varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
        })

        for(i in 1:length(x)){
          results <- varipart(spec.list, env.list, spat.list, type = "parametric")
        }

Ни один из этих методов не работает!Пожалуйста, будьте осторожны, я новичок в списке синтаксиса и циклов.К ошибкам относятся «Предупреждение: в mclapply (output.spectrans.dudi, function (x) {: все запланированные ядра обнаружены ошибки в коде пользователя») и «Ошибка в x * w: нечисловой аргумент для двоичного оператора», соответственно.

1 Ответ

0 голосов
/ 13 декабря 2018

Вы были близки, но я немного объясню, как работает lapplymclapply), потому что вы чувствуете, что вы путаете роль 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 и использовать подход, описанный выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...