Andreï V. Kostyrka
2022-Oct-14 11:07 UTC
[R] Unintended behaviour of stats::time not returning integers for the first cycle
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]]
Eric Berger
2022-Oct-15 07:55 UTC
[R] Unintended behaviour of stats::time not returning integers for the first cycle
Alternatively correct.year <- floor(time(x)+1e-6) On Sat, Oct 15, 2022 at 10:26 AM Andre? V. Kostyrka < andrei.kostyrka at 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 at 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]]
Gabor Grothendieck
2022-Oct-18 17:45 UTC
[R] Unintended behaviour of stats::time not returning integers for the first cycle
The zoo package implements tolerances internally. Converting the ts object to zoo: library(zoo) identical(as.integer(time(as.zoo(x))), true.year) ## [1] TRUE On Sat, Oct 15, 2022 at 3:26 AM Andre? V. Kostyrka <andrei.kostyrka at 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 at 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.-- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com