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