Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comparing units using == #51

Closed
bart1 opened this issue Aug 22, 2017 · 8 comments
Closed

Comparing units using == #51

bart1 opened this issue Aug 22, 2017 · 8 comments

Comments

@bart1
Copy link
Contributor

bart1 commented Aug 22, 2017

I was just trying the units package and got some strange results when comparing to vectors of different units but the same quantity. Here I construct two vectors of the same speed but one in m/s while the other one is in km/h. Two things are there to notice, the order of arguments matters for the results and second even thought the speeds are the same "==" does not consider them the same. For the later issue it probably relates to numerical precision of comparison. An alternative would be to check if the values are the same within some precision limit but I'm not sure if that does not have other unintended consequences or produces unexpected results. An alternative would be to provide some methods that check for equality using some tolerance like all.equal as shown below.

For the order of the arguments I guess one unit is converted in the other one (second into first). An alternative would in case of two different units always convert into SI units so the order of the argument would at least not matter.

> require(units)
> a<-set_units(1:4,m/s)
> bb<-set_units(c(3.6,7.2, 10.8,14.4),km/h)
> a==bb
[1]  TRUE  TRUE FALSE  TRUE
> bb==a
[1] FALSE FALSE FALSE FALSE
> as.numeric(bb)-as.numeric(set_units(a,km/h))
[1] 4.440892e-16 8.881784e-16 1.776357e-15 1.776357e-15
> as.numeric(a)-as.numeric(set_units(bb,m/s))
[1]  0.000000e+00  0.000000e+00 -4.440892e-16  0.000000e+00
> abs(as.numeric(bb)-as.numeric(set_units(a,km/h))) < sqrt(.Machine$double.eps)
[1] TRUE TRUE TRUE TRUE
> sessionInfo()
R version 3.4.1 (2017-06-30)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 17.04

Matrix products: default
BLAS: /usr/lib/openblas-base/libblas.so.3
LAPACK: /usr/lib/libopenblasp-r0.2.19.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=de_DE.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=de_DE.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=de_DE.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] LC_TELEPHONE=C             LC_MEASUREMENT=de_DE.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] units_0.4-5

loaded via a namespace (and not attached):
[1] compiler_3.4.1 tools_3.4.1    udunits2_0.13 
@edzer
Copy link
Member

edzer commented Aug 24, 2017

The first issue is by design; converting to SI may not be desirable in some cases; converting to the first argument seemed easiest. Of course, the user can do manual conversion before any mathematical or logical operations.

For the second one, see R FAQ 7.31 -- it is not up to this package to change this.

@bart1
Copy link
Contributor Author

bart1 commented Aug 25, 2017

Dear Edzer,

I see the problem, I think this would lead to unexpected results for some people. An alternative I could see is to throw a warning when unequal units are compared to suggest to do a explicit conversion before.

If your interested I can create a merge request to that extent

@edzer
Copy link
Member

edzer commented Aug 25, 2017

Are you suggesting that

> set_units(1, m/s) == set_units(3.6, km/h)
[1] TRUE

should always warn?

@edzer
Copy link
Member

edzer commented Aug 25, 2017

It is of course a pity that

> set_units(3.6, km/h) == set_units(1, m/s)
[1] FALSE

but we have

> all.equal(set_units(3.6, km/h), set_units(set_units(1, m/s), km/h))
[1] TRUE

a way out would be adding an all.equal method for units that would give

> all.equal(set_units(3.6, km/h), set_units(1, m/s))
[1] TRUE

I guess that would be more in line with "the R way" of finding near-equality.

@bart1
Copy link
Contributor Author

bart1 commented Aug 25, 2017

I think all.equal might be a way out, but naturally people opt for == i would guess. I was thinking of something like (hypothetical):

> set_units(3.6, km/h) == set_units(1, m/s)
[1] FALSE
Warning message:
In '==' : Non equal units are compared, this might results in numerical inaccuracies due to conversions, consider either explicit conversion or the use of all.equal

The problem with all.equal might be that as far as I'm aware it is not really vectorized so an all.equal method in some cases would need to be used like (hypothetical):

> a<-set_units(1:4,m/s)
> bb<-set_units(c(3.6,7.2, 10.8,14.4),km/h)
> mapply(all.equal, a,b)
[1]  TRUE  TRUE TRUE TRUE

Maybe that is still the best possible solution

edzer added a commit that referenced this issue Aug 25, 2017
@edzer
Copy link
Member

edzer commented Aug 25, 2017

> all.equal(a, bb)
[1] TRUE
> all.equal(bb, a)
[1] TRUE

looks like all.equal is vectorized.

@bart1
Copy link
Contributor Author

bart1 commented Aug 25, 2017

The solution for comparing all elements like == would then be the following I guess (using the devel version of units):

> mapply(units:::all.equal.units,split(a,1:length(a)),split(bb,1:length(bb)))
   1    2    3    4 
TRUE TRUE TRUE TRUE 

@edzer
Copy link
Member

edzer commented Aug 25, 2017

Ah, I see, you want to have a comparison for every element. Yes, something like that.

@edzer edzer closed this as completed Sep 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants