Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the tolerance parameter of all.equal() work?

Tags:

r

Can someone please explain to me the tolerance parameter of all.equal?

The manual says (?all.equal):

tolerance: numeric ≥ 0. Differences smaller than tolerance are not considered.

Numerical comparisons for scale = NULL (the default) are done by first computing the mean absolute difference of the two numerical vectors. If this is smaller than tolerance or not finite, absolute differences are used, otherwise relative differences scaled by the mean absolute difference.

Example:

all.equal(0.3, 0.26, tolerance=0.1)

returns Mean relative difference: 0.1333333

Why is the mean relative difference returned here? Isn't the mean absolute difference of the two numerical vectors smaller than tolerance?

0.3 - 0.26 = 0.04 < 0.1

Thank you!

like image 581
woobert Avatar asked Mar 11 '13 09:03

woobert


People also ask

How do you use all equal?

Description. all. equal(x, y) is a utility to compare R objects x and y testing 'near equality'. If they are different, comparison is still made to some extent, and a report of the differences is returned.

Is equal function r?

Identical function in R is one of the best way to test whether two objects are exactly equal. R Identical function, returns TRUE when two objects are equal and it returns FALSE when two objects are not equal.


1 Answers

If target is greater than tolerance, it seems to check for relative error <= tolerance. That is, abs(current-target)/target <= tolerance in:

all.equal(target, current, tolerance)

For ex:

all.equal(3, 6, tolerance = 1)
# TRUE --> abs(6-3)/3 <= 1

Instead, if target is smaller than tolerance, all.equal uses mean absolute difference.

all.equal(0.01, 4, tolerance = 0.01)
# [1] "Mean absolute difference: 3.99"

all.equal(0.01, 4, tolerance = 0.00999)
# [1] "Mean relative difference: 399"

all.equal(4, 0.01, tolerance = 0.01)
# [1] "Mean relative difference: 0.9975"

However, this is not what the documentation states. To look further as to why this is happening, let's look at the relevant snippet from all.equal.numeric:

# take the example: all.equal(target=0.01, current=4, tolerance=0.01)
cplx <- is.complex(target) # FALSE
out <- is.na(target) # FALSE
out <- out | target == current # FALSE

target <- target[!out] # = target (0.01)
current <- current[!out] # = current (4)

xy <- mean((if(cplx) Mod else abs)(target - current)) # else part is run = 3.99

# scale is by default NULL
what <- if (is.null(scale)) {
    xn <- mean(abs(target)) # 0.01
    if (is.finite(xn) && xn > tolerance) { # No, xn = tolerance
        xy <- xy/xn
        "relative"
    }
    else "absolute" # this is computed for this example
}
else {
    xy <- xy/scale
    "scaled"
}

All that is being checked in the code above (shown only the necessary parts for the example from OP) is: to remove any NA and equal values (of target and current) from target and current. Then compute xy as the mean absolute difference of target and current. But deciding if it is going to be relative or absolute depends on the part what. And here xy is not checked for any conditions. It depends only on xn which is mean(abs(target)).

So, in conclusion, the part pasted by the OP (pasted here for convenience):

If this (meaning, mean absolute difference) is smaller than tolerance or not finite, absolute differences are used, otherwise relative differences scaled by the mean absolute difference.

seems wrong/misleading.

like image 57
Arun Avatar answered Nov 15 '22 20:11

Arun