1

I have a numeric matrix from which I want to retrieve the index given specific values. I am trying the which() function to find values in the matrix.

The problem is that some values are found and some are not.

My matrix is as follows:

x_lat <- as.double(seq(48.0  ,60.0,  by=0.1))
y_long <- as.double(seq(-10.0 ,2.0,   by=0.1))
xv <- as.double(rep(x_lat,each = 121))
yv <- as.double(rep(y_long, 121))

vMatrix <- as.matrix(cbind(xv,yv))

If I want to retrieve the indices where the value -2.3 is TRUE the function returns correctly a vector with the indices where -2.3 appears.

 xx<- which(vMatrix==-2.3,arr.ind=TRUE)

> xx
  [1]    78   199   320   441   562   683   804   925  1046  1167  1288  1409  1530  1651  1772  1893  2014  2135  2256  2377  2498
 [22]  2619  2740  2861  2982  3103  3224  3345  3466  3587  3708  3829  3950  4071  4192  4313  4434  4555  4676  4797  4918  5039
 [43]  5160  5281  5402  5523  5644  5765  5886  6007  6128  6249  6370  6491  6612  6733  6854  6975  7096  7217  7338  7459  7580
 [64]  7701  7822  7943  8064  8185  8306  8427  8548  8669  8790  8911  9032  9153  9274  9395  9516  9637  9758  9879 10000 10121
 [85] 10242 10363 10484 10605 10726 10847 10968 11089 11210 11331 11452 11573 11694 11815 11936 12057 12178 12299 12420 12541 12662
[106] 12783 12904 13025 13146 13267 13388 13509 13630 13751 13872 13993 14114 14235 14356 14477 14598

But for some numbers (that appear in the matrix) the function does not work, e.g.,

 xx<- which(vMatrix==-2.2,arr.ind=TRUE)

> xx
integer(0)
10 Rep
  • 2,217
  • 7
  • 19
  • 33
armg
  • 13
  • 3

1 Answers1

0

Floating point numbers can be misleading. Two such numbers are usually not "equal", even though the console may display the same output. The machine only has a certain accuracy with which it can represent the numbers.

Here's a simple example:

a <- 0.15 - 1/8 
b <- 0.025
> a
[1] 0.025
> b
[1] 0.025

However, if we compare these numbers with "==", we obtain:

> a==b
[1] FALSE

That is because there are differences resulting from the floating point arithmetic which are beyond the machine's accuracy:

> a-b
[1] -6.938894e-18

Probably you can resolve the issue by simply rounding the numbers in the matrix to the necessary amount of relevant digits, like, e.g.,

xx<- which(round(vMatrix,3)==-2.2,arr.ind=TRUE)
RHertel
  • 23,412
  • 5
  • 38
  • 64
  • 1
    Values on the matrix have just one decimal so I didn't think it made sense rounding them to a higher number of decimals. I see now how it makes sense. Thanks! – armg Sep 15 '15 at 10:36
  • Using `round` is not a very good way of comparing numbers with floating point tolerance. `all.equal` implements a better way. More details: http://stackoverflow.com/a/9508558/1968 – Konrad Rudolph Sep 15 '15 at 11:00
  • @KonradRudolph thanks for the great reference..In this case I would need to implement `all.equal()` using `which()` in a different manner, but that is another problem – armg Sep 16 '15 at 09:17
  • turns out I can loop through the matrix using `all.equal` and `which()`, tip was a the end of the reference... thus.. `which(mapply(function(x, y) {isTRUE(all.equal(x, y))}, round(vMatrix[,2],3), -2.2), arr.ind=TRUE)` works as well – armg Sep 16 '15 at 13:07