Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test for equality among all elements of a single numeric vector

Tags:

equality

r

vector

People also ask

How do you check if all elements in an vector are equal?

A simple solution to check if all elements of a vector are equal is using the std::adjacent_find function. It returns the first occurrence of adjacent elements that satisfies a binary predicate, or end of the range if no such pair is found.

How do you check for equality of a vector in R?

Check if Two Objects are Equal in R Programming – setequal() Function. setequal() function in R Language is used to check if two objects are equal. This function takes two objects like Vectors, dataframes, etc. as arguments and results in TRUE or FALSE, if the Objects are equal or not.

How do I see all values in a vector in R?

R – all() function all() function in R Language will check in a vector whether all the values are true or not. Parameters: x: vector.

What is a numeric vector?

x <- c(1, 2, 3) x is a numeric vector. These are the most common kind. They are numeric objects and are treated as double precision real numbers. To explicitly create integers, add a L at the end.


Why not simply using the variance:

var(x) == 0

If all the elements of x are equal, you will get a variance of 0.


If they're all numeric values then if tol is your tolerance then...

all( abs(y - mean(y)) < tol ) 

is the solution to your problem.

EDIT:

After looking at this, and other answers, and benchmarking a few things the following comes out over twice as fast as the DWin answer.

abs(max(x) - min(x)) < tol

This is a bit surprisingly faster than diff(range(x)) since diff shouldn't be much different than - and abs with two numbers. Requesting the range should optimize getting the minimum and maximum. Both diff and range are primitive functions. But the timing doesn't lie.


I use this method, which compares the min and the max, after dividing by the mean:

# Determine if range of vector is FP 0.
zero_range <- function(x, tol = .Machine$double.eps ^ 0.5) {
  if (length(x) == 1) return(TRUE)
  x <- range(x) / mean(x)
  isTRUE(all.equal(x[1], x[2], tolerance = tol))
}

If you were using this more seriously, you'd probably want to remove missing values before computing the range and mean.


You can just check all(v==v[1])


> isTRUE(all.equal( max(y) ,min(y)) )
[1] TRUE
> isTRUE(all.equal( max(x) ,min(x)) )
[1] FALSE

Another along the same lines:

> diff(range(x)) < .Machine$double.eps ^ 0.5
[1] FALSE
> diff(range(y)) < .Machine$double.eps ^ 0.5
[1] TRUE

You can use identical() and all.equal() by comparing the first element to all others, effectively sweeping the comparison across:

R> compare <- function(v) all(sapply( as.list(v[-1]), 
+                         FUN=function(z) {identical(z, v[1])}))
R> compare(x)
[1] FALSE
R> compare(y)
[1] TRUE
R> 

That way you can add any epsilon to identical() as needed.


Since I keep coming back to this question over and over, here's an Rcpp solution that will generally be much much faster than any of the R solutions if the answer is actually FALSE (because it will stop the moment it encounters a mismatch) and will have the same speed as the fastest R solution if the answer is TRUE. For example for the OP benchmark, system.time clocks in at exactly 0 using this function.

library(inline)
library(Rcpp)

fast_equal = cxxfunction(signature(x = 'numeric', y = 'numeric'), '
  NumericVector var(x);
  double precision = as<double>(y);

  for (int i = 0, size = var.size(); i < size; ++i) {
    if (var[i] - var[0] > precision || var[0] - var[i] > precision)
      return Rcpp::wrap(false);
  }

  return Rcpp::wrap(true);
', plugin = 'Rcpp')

fast_equal(c(1,2,3), 0.1)
#[1] FALSE
fast_equal(c(1,2,3), 2)
#[2] TRUE