I'm really confused. Steve's example wasn't a scalar x, it was a vector. Your zapsmall() proposal wouldn't zap it to zero, and I don't see why summary() would if it was using your proposal.

Duncan Murdoch

On 17/12/2023 8:43 a.m., Gregory R. Warnes wrote:
Isn’t that the correct outcome?  The user can change the number of digits if 
they want to see small values…


--
Change your thoughts and you change the world.
--Dr. Norman Vincent Peale

On Dec 17, 2023, at 12:11 AM, Steve Martin <stevemartin...@gmail.com> wrote:

Zapping a vector of small numbers to zero would cause problems when
printing the results of summary(). For example, if
zapsmall(c(2.220446e-16, ..., 2.220446e-16)) == c(0, ..., 0) then
print(summary(2.220446e-16), digits = 7) would print
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
        0          0            0           0           0          0

The same problem can also appear when printing the results of
summary.glm() with show.residuals = TRUE if there's little dispersion
in the residuals.

Steve

On Sat, 16 Dec 2023 at 17:34, Gregory Warnes <g...@warnes.net> wrote:

I was quite suprised to discover that applying `zapsmall` to a scalar value has 
no apparent effect.  For example:

y <- 2.220446e-16
zapsmall(y,)
[1] 2.2204e-16

I was expecting zapsmall(x)` to act like

round(y, digits=getOption('digits'))
[1] 0

Looking at the current source code, indicates that `zapsmall` is expecting a 
vector:

zapsmall <-
function (x, digits = getOption("digits"))
{
    if (length(digits) == 0L)
        stop("invalid 'digits'")
    if (all(ina <- is.na(x)))
        return(x)
    mx <- max(abs(x[!ina]))
    round(x, digits = if (mx > 0) max(0L, digits - as.numeric(log10(mx))) else 
digits)
}

If `x` is a non-zero scalar, zapsmall will never perform rounding.

The man page simply states:
zapsmall determines a digits argument dr for calling round(x, digits = dr) such 
that values close to zero (compared with the maximal absolute value) are 
‘zapped’, i.e., replaced by 0.

and doesn’t provide any details about how ‘close to zero’ is defined.

Perhaps handling the special when `x` is a scalar (or only contains a single 
non-NA value)  would make sense:

zapsmall <-
function (x, digits = getOption("digits"))
{
    if (length(digits) == 0L)
        stop("invalid 'digits'")
    if (all(ina <- is.na(x)))
        return(x)
    mx <- max(abs(x[!ina]))
    round(x, digits = if (mx > 0 && (length(x)-sum(ina))>1 ) max(0L, digits - 
as.numeric(log10(mx))) else digits)
}

Yielding:

y <- 2.220446e-16
zapsmall(y)
[1] 0

Another edge case would be when all of the non-na values are the same:

y <- 2.220446e-16
zapsmall(c(y,y))
[1] 2.220446e-16 2.220446e-16

Thoughts?


Gregory R. Warnes, Ph.D.
g...@warnes.net
Eternity is a long time, take a friend!



        [[alternative HTML version deleted]]

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

        [[alternative HTML version deleted]]

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to