How to check if each element in a vector is integer or not in R?

走远了吗. 提交于 2019-12-19 05:32:54

问题


Say, I have a vector y, and I want to check if each element in y is integer or not, and if not, stop with an error message. I tried is.integer(y), but it does not work.


回答1:


The simplest (and fastest!) thing is probably this:

stopifnot( all(y == floor(y)) )

...So trying it out:

y <- c(3,4,9)
stopifnot( all(y == floor(y)) ) # OK

y <- c(3,4.01,9)
stopifnot( all(y == floor(y)) ) # ERROR!

If you want a better error message:

y <- c(3, 9, NaN)
if (!isTRUE(all(y == floor(y)))) stop("'y' must only contain integer values")



回答2:


you could do:

   y <- c(3,3.1,1,2.3)
   (y - floor(y)) == 0
    [1]  TRUE FALSE  TRUE FALSE

or

   (y - round(y)) == 0

and if you want a single TRUE or FALSE for the whole thing, put it in all(), e.g.:

   all((y - round(y)) == 0)
    [1] FALSE



回答3:


Here's another way (using the same trick as Justin of comparing each number to that number coerced into the 'integer' type):

R> v1 = c(1,2,3)
R> v2 = c(1,2,3.5)
R> sapply(v1, function(i) i == as.integer(i))
[1] TRUE TRUE TRUE
R> sapply(v2, function(i) i == as.integer(i))
[1]  TRUE  TRUE FALSE

To make your test:

R> all(sapply(v2, function(i) i == as.integer(i)))
[1] FALSE



回答4:


Not sure which is faster Tim's way or this, but:

> x <- 1:5
> y <- c(x, 2.0)
> z <- c(y, 4.5)
> all.equal(x, as.integer(x))
[1] TRUE
> all.equal(y, as.integer(y))
[1] TRUE
> all.equal(z, as.integer(z))
[1] "Mean relative difference: 0.1111111"
> 

or:

all((z - as.integer(z))==0)



回答5:


I went in a completely different direction then Tim (I like his better though my approach works on a mixed vector that's a character vector with integers etc.):

int.check <- function(vect) {
    vect <- as.character(vect)
    sapply(vect, function(x) all(unlist(strsplit(x, ""))%in% 0:9))
}

x <- c(2.0, 1111,"x", 2.4)
int.check(x)

EDIT: altered the function as it only worked on character vectors.

This works on vectors of the class character as well in case you have a character vector with various number intermixed but that have been coerced to character.




回答6:


checking the following helps with a crisp if condition which we can use on scripting.

sff <- 5

if(!(is.integer(sff) == is.character(sff))){ 
  sff
} else {
  "hello"
}

gives

hello

sff <- 'a' gives 'a' as the result.




回答7:


If you have floating-point representation error, try:

round( y, TOLERANCE.DIGITS ) %% 1 == 0

In my application, I had seriously brutal floating-point representation error, such that:

> dictionary$beta[3]
[1] 89
> floor(dictionary$beta[3])
[1] 88
> as.integer( dictionary$beta )[3]
[1] 88
> dictionary$beta[3] %% 1
[1] 1

the remainder divided by one was one. I found that I had to round before I took the integer. I think all of these tests would fail in the case where you wanted the above 89 to count as an integer. The "all.equal" function is meant to be the best way to handle floating-point representation error, but:

all.equal( 88, 89 );

as in my case, would have (and did) given a false negative for an integer value check.

EDIT: In benchmarking, I found that:

(x == as.integer(x)) 

was universally the best performer.

(x == floor(x))
((x - as.integer(x)) == 0)

usually worked well, often just as fast.

(x %% 1 <= tolerance)

works, but not as quickly as the others

!(is.character(all.equal(x, as.integer(x)))) 

when the vector wasn't integers, had terrible performance (certainly because it goes to the trouble of estimating the difference).

identical(x, as.integer(x)) 

when the vector was all integer values, returned the incorrect result (assuming the question was meant to check for integer values, not integer types).



来源:https://stackoverflow.com/questions/10113933/how-to-check-if-each-element-in-a-vector-is-integer-or-not-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!