2015-07-21 10 views
9

Sto usando una funzione lapply su un elenco di file multipli. C'è un modo in cui posso saltare la funzione sul file corrente senza restituire nulla e saltare al prossimo file nella lista dei file?R: funzione lapply - saltare il loop della funzione corrente

Per essere precisi, ho un'istruzione if che controlla una condizione e vorrei passare al file successivo se l'istruzione restituisce FALSE.

+1

Si potrebbe utilizzare la condizione per selezionare un sottoinsieme di la tua lista e memorizza questo sottoinsieme in una variabile separata che fornisci a 'lapply'. – RHertel

+0

@RHertel Dal momento che stanno elaborando un elenco di file e non una porzione di dati già presente nella RAM, è improbabile che abbiano le informazioni per suddividere i file in anticipo. –

risposta

8

lapply sarà sempre restituire un elenco della stessa lunghezza dello X fornito. È possibile semplicemente impostare gli elementi su qualcosa che è possibile filtrare in seguito.

Per esempio, se si ha la funzione di parsefile

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

e si esegue su un vettore runif(10,-5,5)

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

poi avrete la vostra lista piena di risposte e NULL s

È possibile impostare il sotto NULL facendo ...

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

L'ultimo bit può essere migliorato: 'list.condition <-! Vapply (result, is.null, logical (1))'. Altrimenti un'ottima risposta. – sdgfsdh

+0

@sdgfsdh nice ... modificato per riflettere. –

+0

Non dimenticare un '!' – sdgfsdh

0

È possibile definire una funzione personalizzata da utilizzare nella chiamata a lapply(). Ecco alcuni esempi di codice che itera su un elenco di file ed elabora un file solo se il nome non contiene il numero 3 (un po 'forzato, ma si spera che questo diventa il punto attraverso):

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 
2

Come già risposto dagli altri, non penso che sia possibile procedere alla successiva iterazione senza restituire qualcosa utilizzando la famiglia di funzioni *apply.

In questi casi, utilizzo il metodo di Dean MacGregor, con una piccola modifica: io uso NA anziché NULL, il che rende più semplice il filtraggio dei risultati.

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

Un rapido punto di riferimento

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

illustra che la soluzione NA è un po 'più veloce rispetto alla soluzione che utilizza 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