2012-03-12 9 views
13

Ho affrontato uno strano comportamento in R con la funzione sapply(). Questa funzione dovrebbe restituire un vettore, ma nel caso particolare in cui gli dai un vettore vuoto, restituisce una lista.Perché sapply() restituisce una lista?

comportamento corretto con un vettore:

a = c("A", "B", "C") 
a[a == "B"] # Returns "B" 
a[sapply(a, function(x) {x == "B"})] # Returns "B" 

comportamento corretto con un valore NULL:

a = NULL 
a[a == "B"] # Returns NULL 
a[sapply(a, function(x) {x == "B"})] # Returns NULL 

comportamento sconosciuto con un vettore vuoto:

a = vector() 
a[a == "B"] # Returns NULL 
a[sapply(a, function(x) {x == "B"})] # Erreur : type 'list' d'indice incorrect 

messaggio di errore Come con questa dichiarazione:

a[list()] # Erreur dans a[list()] : type 'list' d'indice incorrect 

Perché? E 'un errore?

A causa di questo strano comportamento, utilizzo unlist(lapply()).

+4

Proteggi- non è mai un bug –

+2

@ChrisBeeley - Mai un bug, sempre una "feature" ;-) R (e S) hanno un po 'di "caratteristiche" tutt'altro che ideali, e questo è uno di loro . '1: 0' è un altro ... – Tommy

risposta

17

Il vero motivo di ciò è che sapply non sa quale funzione verrà restituita senza chiamarla. Nel tuo caso la funzione restituisce un logical, ma poiché sapply viene fornito un elenco vuoto, la funzione non viene mai chiamata. Pertanto, deve venire con un tipo e il valore predefinito è list.

... Per questo motivo (e per prestazioni), è stato introdotto vapply! Richiede di specificare il tipo di valore di ritorno (e la lunghezza). Questo gli permette di fare la cosa giusta. Come bonus, è anche più veloce!

sapply(LETTERS[1:3], function(x) {x == "B"}) # F, T, F 
sapply(LETTERS[0], function(x) {x == "B"}) # list() 

vapply(LETTERS[1:3], function(x) {x == "B"}, logical(1)) # F, T, F 
vapply(LETTERS[0], function(x) {x == "B"}, logical(1)) # logical() 

Vedi ?vapply per maggiori informazioni.

2

In realtà entrambi restituiscono uno list. L'unica differenza tra i due è quando si tenta di indicizzare NULL restituisce sempre NULL (anche se l'indice era un elenco), ma quando si tenta di indicizzare un vettore vuoto, controlla l'indice e si rende conto che è un list.

a = NULL 
res = sapply(a, function(x) x == "B") # Res is an empty list 
a[res] # returns NULL, because any index of NULL is NULL. 


a = vector() 
res = sapply(a, function(x) x == "B") # Still an empty list. 
a[res] # but you can't index a vector with a list! 
6

L'aiuto per la funzione ?sapply ha questa nel Valore sezione

For ‘sapply(simplify = TRUE)’ and ‘replicate(simplify = TRUE)’: if 
‘X’ has length zero or ‘n = 0’, an empty list. 

In entrambi i casi i tuoi:

> length(NULL) 
[1] 0 
> length(vector()) 
[1] 0 

Di qui sapply() rendimenti:

> sapply(vector(), function(x) {x == "B"}) 
list() 
> sapply(NULL, function(x) {x == "B"}) 
list() 

vostro errore non è da sapply() ma da [ come questo dimostra:

> a[list()] 
Error in a[list()] : invalid subscript type 'list' 

Quindi il problema è legato al modo in cui viene eseguita sottoinsiemi di NULL e un vettore vuoto (vector()). Niente a che vedere con sapply(). In entrambi i casi restituisce un output coerente, una lista vuota.

Problemi correlati