[R] Unintended behaviour of stats::time not returning integers for the first cycle

Martin Maechler m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Wed Oct 19 10:05:31 CEST 2022


>>>>> Andreï V Kostyrka 
>>>>>     on Tue, 18 Oct 2022 16:26:28 +0400 writes:

    > Sure, this works, and I was thinking about this solution, but it seems like
    > a dirty one-time trick. I was wondering whether the following 3 lines could
    > be considered for inclusion by the core developers, but did not know which
    > mailing list to write to. 

As Jeff alluded to, *every* message to this list has a footer
with a link to *the POSTING GUIDE"  ...

and from there you quickly learn it is 'R-devel' (instead of 'R-help').

Now that we have already half a dozen messages here, let's keep
the whole thread here, even if only for ease of reading the list archives(!)

    > Here is my proposal:

    > correctTime <- function (x, offset = 0, ...) { # Changes
    > stats:::time.default
    >  n <- if (is.matrix(x)) nrow(x) else length(x)
    >  xtsp <- attr(hasTsp(x), "tsp")
    >  y <- seq.int(xtsp[1L], xtsp[2L], length.out = n) + offset/xtsp[3L]
    >  round.y <- round(y)
    >  near.integer <- abs(round.y - y) < sqrt(.Machine$double.eps)
    >  y[near.integer] <- round.y[near.integer]
    >  tsp(y) <- xtsp
    > y
    > }

Yes, some such change does make sense to me, too.
As the computations above are relatively costly (compared to the
current  time.default()  implementation),
and also for strict back compatibility reasons, I think the
correction should only happen when the user asks for it,  say by
using a new argument 'roundYear = TRUE'  (where the default
remains roundYear=FALSE).

Martin Maechler
ETH Zurich  and  R Core tam

    > x <- ts(2:252, start = c(2002, 2), freq = 12)
    > d <- seq.Date(as.Date("2002-02-01"), to = as.Date("2022-12-01"), by =
    > "month")
    > true.year <- rep(2002:2022, each = 12)[-1]
    > wrong.year <- floor(as.numeric(time(x)))
    > print(as.numeric(time(x))[240], 20) # 2021.9999999999997726, the floor of
    > which is 2021
    > print(correctTime(x)[240], 20) # 2022

    > On Sat, Oct 15, 2022 at 11:56 AM Eric Berger <ericjberger using gmail.com> wrote:

    >> Alternatively
    >> 
    >> correct.year <- floor(time(x)+1e-6)
    >> 
    >> On Sat, Oct 15, 2022 at 10:26 AM Andreï V. Kostyrka <
    >> andrei.kostyrka using gmail.com> wrote:
    >> 
    >>> Dear all,
    >>> 
    >>> 
    >>> 
    >>> I was using stats::time to obtain the year as a floor of it, and
    >>> encountered a problem: due to a rounding error (most likely due to its
    >>> reliance on the base::seq.int internally, but correct me if I am wrong),
    >>> the actual number corresponding to the beginning of a year X can still be
    >>> (X-1).9999999..., resulting in the following undesirable behaviour.
    >>> 
    >>> 
    >>> 
    >>> One of the simplest ways of getting the year from a ts object is
    >>> floor(time(...)). However, if the starting time cannot be represented
    >>> nicely as a power of 2, then, supposedly integer time does not have a
    >>> .000000... mantissa:
    >>> 
    >>> 
    >>> 
    >>> x <- ts(2:252, start = c(2002, 2), freq = 12)
    >>> 
    >>> d <- seq.Date(as.Date("2002-02-01"), to = as.Date("2022-12-01"), by =
    >>> "month")
    >>> 
    >>> true.year <- rep(2002:2022, each = 12)[-1]
    >>> 
    >>> wrong.year <- floor(as.numeric(time(x)))
    >>> 
    >>> tail(cbind(as.character(d), true.year, wrong.year), 15) # Look at
    >>> 2022-01-01
    >>> 
    >>> print(as.numeric(time(x))[240], 20) # 2021.9999999999997726, the floor of
    >>> which is 2021
    >>> 
    >>> 
    >>> 
    >>> Yes, I have read the 'R inferno' book and know the famous '0.3 != 0.7 -
    >>> 0.4' example, but I believe that the expected / intended behaviour would
    >>> be
    >>> actually returning round years for the first observation in a year. This
    >>> could be achieved by rounding the near-integer time to integers.
    >>> 
    >>> 
    >>> 
    >>> Since users working with dates are expecting to get exact integer years
    >>> for
    >>> the first cycle of a ts, this should be changed. Thank you in advance for
    >>> considering a fix.
    >>> 
    >>> 
    >>> 
    >>> Yours sincerely,
    >>> 
    >>> Andreï V. Kostyrka
    >>> 
    >>> [[alternative HTML version deleted]]
    >>> 
    >>> ______________________________________________
    >>> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
    >>> https://stat.ethz.ch/mailman/listinfo/r-help
    >>> PLEASE do read the posting guide
    >>> http://www.R-project.org/posting-guide.html
    >>> and provide commented, minimal, self-contained, reproducible code.
    >>> 
    >> 

    > [[alternative HTML version deleted]]

    > ______________________________________________
    > R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
    > https://stat.ethz.ch/mailman/listinfo/r-help
    > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
    > and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list