Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you check for a scalar in R?

Tags:

r

I am interested identifying numeric scalars like:

doub <- 3.14
intg <- 8L

I know that these are treated as length one vectors. Thus, for any R object x, is is.vector(x) && length(x) == 1 the right way to check whether x is a scalar? length(x) == 1 by itself is not sufficient as it returns a true, when it should return false, for a data frame with one column or a list with one element.

Is there a reason why there is no such function is.scalar implemented in base R? For some reason the two I could find in other functions fail for the data frame case mentioned previously, these are:

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

Why are the results of these two function calls different to my understanding (and definition) of how a is.scalar function should work?

like image 231
Alex Avatar asked Jun 29 '16 00:06

Alex


People also ask

How do you find a scalar in R?

vector(x) && length(x) == 1 the right way to check whether x is a scalar? length(x) == 1 by itself is not sufficient as it returns a true, when it should return false, for a data frame with one column or a list with one element.

Are there scalars in R?

First, R doesn't have scalar type which means the smallest unit in R language is vector. For instance, “John” is a vector that is represented as c(“John”), Likewise when we see a scalar value100, it is actually a vector of length 1 as c(100).

What's a scalar in R?

The simplest object type in R is a scalar. A scalar object is just a single value like a number or a name.

What is a scalar datatype?

A scalar data type is something that has a finite set of possible values, following some scale, i.e. each value can be compared to any other value as either equal, greater or less. Numeric values (floating point and integer) are the obvious examples, while discrete/enumerated values can also be considered scalar.


2 Answers

I think is.atomic suits your needs.

For why is.vector is probably incompatible, see, e.g.:

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

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

On your objects:

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
like image 177
MichaelChirico Avatar answered Oct 11 '22 00:10

MichaelChirico


Building on the answer by @MichaelChirico, there are a couple of other things that is.scalar() should check for.

Firstly, complex numbers are not usually regarded as scalars (although I think this usage may vary between disciplines).

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

so we should also check for complex numbers. The simple, but naive, way to do this is to use is.complex

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

Unfortunately, this is not quite right, because is.complex just tests whether the class is "complex". But real numbers can have class=complex if their imaginary component is zero.

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

So to test for real numbers we are better off to check that the imaginary component is zero using Im(x)==0. So, this leads us to a test for scalars that look like this

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

More trivially, characters ought also be eliminated

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

Note that we test for is.character(x) before Im(x)==0 so that lazy evaluation ensures that the function never tries to find the imaginary component of a character, which would throw an error.

like image 42
dww Avatar answered Oct 10 '22 23:10

dww