2016-06-29 20 views
10

mi interessa identificare scalari numerici come:Come si controlla uno scalare in R?

doub <- 3.14 
intg <- 8L 

so che questi sono trattati come lunghezza vettori. Pertanto, per qualsiasi oggetto R x, è is.vector(x) && length(x) == 1 il modo corretto per verificare se x è uno scalare? length(x) == 1 di per sé non è sufficiente in quanto restituisce un valore true, quando deve restituire false, per un frame di dati con una colonna o un elenco con un elemento.

C'è un motivo per cui non esiste una tale funzione is.scalar implementata nella base R? Per qualche ragione i due sono riuscito a trovare in altre funzioni di rifiuto per la caso della struttura di dati accennato in precedenza, questi sono:

assertthat::is.scalar(data.frame(a = 1:2)) 
lambda.tools::is.scalar(data.frame(a = 1:2)) 

Perché sono i risultati di queste due funzioni chiamate diverso per la mia comprensione (e definizione) di come un La funzione is.scalar dovrebbe funzionare?

+2

Probabilmente vuoi 'is.atomic' invece di' is.vector'. –

+2

qual è la differenza tra i due? – Alex

+0

Vedere '? Is.atomic':" È comune chiamare i "vettori atomici" di tipi atomici, ma si noti che 'is.vector' impone ulteriori restrizioni: un oggetto può essere atomico ma non un vettore (in questo senso). " – MichaelChirico

risposta

8

Penso che is.atomic soddisfi le tue esigenze.

Per il motivo per cui is.vector è probabilmente incompatibili, vedi ad esempio:

is.atomic(list(1)) 
# [1] FALSE 

is.vector(list(1)) 
# [1] TRUE 

Sulla gli oggetti:

is.scalar <- function(x) is.atomic(x) && length(x) == 1L 

is.scalar(doub) 
# [1] TRUE 

is.scalar(intg) 
# [1] TRUE 

is.scalar(c(doub, intg)) 
# [1] FALSE 
8

Basandosi sul answer da @MichaelChirico, ci sono un paio di altre cose che is.scalar() dovrebbe controllare.

In primo luogo, i numeri complessi non sono generalmente considerati scalari (anche se penso che questo utilizzo possa variare da una disciplina all'altra).

comp <- 2+3i 
is.scalar <- function(x) is.atomic(x) && length(x) == 1L 
is.scalar(comp) 
# TRUE 

quindi dovremmo anche verificare la presenza di numeri complessi. La semplice, ma ingenua, modo per farlo è quello di utilizzare is.complex

is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.complex(x) 
is.scalar(comp) 
# FALSE 

Purtroppo, questo non è giusto, perché is.complex mette alla prova solo se la classe è "complex". Ma i numeri reali possono avere classe = complesso se il loro componente immaginario è zero.

is.complex(2+0i) 
# [1] TRUE 

Quindi, per testare per i numeri reali siamo meglio a controllare che il componente immaginario è zero utilizzando Im(x)==0. Quindi, questo ci porta ad un test per scalari che assomigliano a questo

is.scalar <- function(x) is.atomic(x) && length(x) == 1L && Im(x)==0 

Più banalmente, i personaggi dovrebbero anche essere eliminati

is.scalar("x") 
# TRUE 
is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.character(x) && Im(x)==0 
is.scalar("x") 
# FALSE 

noti che ci prova per is.character(x) prima Im(x)==0 in modo che la valutazione pigra assicura che la funzione non cerca mai di trovare la componente immaginaria di un personaggio, che genera un errore.

+0

Quindi perché non usare semplicemente 'is.scalar <- function (x) length (x) == 1L && is.vector (x, mode =" numeric ")'? – Wastl

+1

@Wastl Dipende dal tuo scopo ed esattamente quello che vuoi testare, ma usando la tua definizione 'is.scalar (x)' fallirebbe per es. 'x = 1 + 0i',' x = NA' e 'x = 1; attr (x, 'foo') = 1' – dww

Problemi correlati