R: функция привязки - пропускание текущей петли функции

Я использую функцию lapply над списком нескольких файлов. Есть ли способ, с помощью которого я могу пропустить функцию в текущем файле, не возвращая ничего, и просто перейдите к следующему файлу в списке файлов?

Чтобы быть точным, у меня есть оператор if, который проверяет условие, и я хотел бы перейти к следующему файлу, если оператор возвращает FALSE.

Ответ 1

lapply всегда возвращает список той же длины, что и предоставленный им X Вы можете просто установить элементы на что-то, что вы можете позже отфильтровать.

Например, если у вас есть функция parsefile

parsefile <-function(x) {
  if(x>=0) {
    x
  } else {
    NULL
  }
}

и вы запускаете его на векторном runif(10,-5,5)

result<-lapply(runif(10,-5,5), parsefile)

тогда ваш список будет заполнен ответами и NULL

Вы можете выделить NULL, выполнив...

result[!vapply(result, is.null, logical(1))]

Ответ 2

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

В таких случаях я использую метод Dean MacGregor с небольшим изменением: вместо NULL я использую NA, что облегчает фильтрацию результатов.

files <- list("file1.txt", "file2.txt", "file3.txt")

parse_file <- function(file) {
  if(file.exists(file)) {
    readLines(file)
  } else {
    NA
  }
}

results <- lapply(files, parse_file)
results <- results[!is.na(results)]

Быстрый тест

res_na   <- list("a",   NA, "c")
res_null <- list("a", NULL, "c")
microbenchmark::microbenchmark(
  na = res_na[!is.na(res_na)],
  null = res_null[!vapply(res_null, is.null, logical(1))]
)

иллюстрирует, что решение NA довольно немного быстрее, чем решение, использующее NULL:

Unit: nanoseconds
expr  min   lq    mean median   uq   max neval
  na    0    1  410.78    446  447  5355   100
null 3123 3570 5283.72   3570 4017 75861   100

Ответ 3

Вы можете определить пользовательскую функцию, которая будет использоваться при вызове lapply(). Вот пример кода, который выполняет итерацию по списку файлов и обрабатывает файл только в том случае, если имя не содержит номер 3 (немного надуманный, но, надеюсь, это получает точку):

files <- as.list(c("file1.txt", "file2.txt", "file3.txt"))

fun <- function(x) {
    test <- grep("3", x)                     // check for files with "3" in their name
    if (length(test) == 0) {                 // replace with your statement here
        // process the file here
    }
    // otherwise do not process the file
}

result <- lapply(files, function(x) fun(x))  // call lapply with custom function