DavidS
DavidS

Reputation: 51

In R, why does is.integer(1) return FALSE?

In R, is.integer(1) returns FALSE and class(1) returns "numeric" while is.integer(1:1) returns TRUE and class(1:1) returns "integer". Why does not is.integer(1) return TRUE?

Comparing the printed values to the output of class() or typeof() leads to counter intuitive results. E.g.

x1=seq(from=1, to=5, by=1) 
x2=1:5
x1 
[1] 1 2 3 4 5 
x2 
[1] 1 2 3 4 5 
class(x1) 
[1] "numeric" 
class(x2)
[1] "integer"

To determine if x1 contains integer values I need to use all(as.integer(x1)==x1). Is there an easier way?

class() can return an array, e.g. an ordered factor. Shouldn't class(1) return c("numeric", "integer")?

Upvotes: 5

Views: 2703

Answers (1)

Rich Scriven
Rich Scriven

Reputation: 99331

Hopefully this helps clear things up a bit. Your example doesn't necessarily tell the whole truth. In fact, the vector type returned from seq depends on which arguments you use. Here's a look at the example set-ups from ?seq.

seqList <- list(
    fromto = seq(from = 1, to = 5),
    fromtoby = seq(from = 1, to = 5, by = 1),
    fromtolengthout = seq(from = 1, to = 5, length.out = 5),
    alongwith = seq(along.with = 5),
    from = seq(from = 1),
    lengthout = seq(length.out = 5),
    binary = 1:5
)

With the result, we can see that when we use the by argument (as you did), the result is not of integer type. The type of result is changed to numeric once argument checking occurs (I think, correct me if I'm wrong).

str(seqList)
# List of 7
#  $ fromto         : int [1:5] 1 2 3 4 5
#  $ fromtoby       : num [1:5] 1 2 3 4 5
#  $ fromtolengthout: num [1:5] 1 2 3 4 5
#  $ alongwith      : int 1
#  $ from           : int 1
#  $ lengthout      : int [1:5] 1 2 3 4 5
#  $ binary         : int [1:5] 1 2 3 4 5

seq is a generic function that dispatches to different methods based on the supplied arguments. It's all explained in ?seq. It's worth a read. There are also seq.int, seq_len, and seq_along which are also different from seq. Now in reference to your question

To determine if x1 contains integer values I need to use all(as.integer(x1)==x1). Is there an easier way?

That check might cause some issues, as factors are also integers

f <- factor(letters[1:5])
x <- 1:5
f == x
# [1] FALSE FALSE FALSE FALSE FALSE
as.integer(f) == x
# [1] TRUE TRUE TRUE TRUE TRUE

I'd go with inherits or typeof. The first returns a logical, which would work nicely in if statements. And typeof returns a character string of the vector type.

look <- function(x) {
    c(class = class(x), typeof = typeof(x), 
      mode = mode(x), inherits = inherits(x, "integer"))
}
noquote(do.call(rbind, lapply(seqList, look)))
#                 class   typeof  mode    inherits
# fromto          integer integer numeric TRUE    
# fromtoby        numeric double  numeric FALSE   
# fromtolengthout numeric double  numeric FALSE   
# alongwith       integer integer numeric TRUE    
# from            integer integer numeric TRUE    
# lengthout       integer integer numeric TRUE    
# binary          integer integer numeric TRUE    

Reading the help files is very informative. I'm definitely not an expert on this stuff, so if I've gotten anything wrong here, please let me know. Here's something more to stimulate the curiosity:

is.integer(1)
# [1] FALSE
is.integer(1L)
# [1] TRUE

Upvotes: 4

Related Questions