[Rd] zapsmall(x) for scalar x

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Sun Dec 17 15:17:03 CET 2023


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 <stevemartin041 using 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 <greg using 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.
>>> greg using warnes.net
>>> Eternity is a long time, take a friend!
>>>
>>>
>>>
>>>         [[alternative HTML version deleted]]
>>>
>>> ______________________________________________
>>> R-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list