How to avoid that anytime(<numeric>) “updates by reference”?

送分小仙女□ 提交于 2019-12-08 15:41:59

问题


I want to convert a numeric variable to POSIXct using anytime. My issue is that anytime(<numeric>) converts the input variable as well - I want to keep it.

Simple example:

library(anytime)
t_num <- 1529734500
anytime(t_num)
# [1] "2018-06-23 08:15:00 CEST"
t_num
# [1] "2018-06-23 08:15:00 CEST"

This differs from the 'non-update by reference' behaviour of as.POSIXct in base R:

t_num <- 1529734500
as.POSIXct(t_num, origin = "1970-01-01")
# [1] "2018-06-23 08:15:00 CEST"
t_num
# 1529734500

Similarly, anydate(<numeric>) also updates by reference:

d_num <- 17707
anydate(d_num)
# [1] "2018-06-25"
d_num
# [1] "2018-06-25"

I can't find an explicit description of this behaviour in ?anytime. I could use as.POSIXct as above, but does anyone know how to handle this within anytime?


回答1:


You could hack it like this:

library(anytime)
t_num <- 1529734500
anytime(t_num+0)
# POSIXct[1:1], format: "2018-06-23 08:15:00"
t_num
# [1] 1529734500

Note that an integer input will be treated differently:

t_int <- 1529734500L
anytime(t_int)
# POSIXct[1:1], format: "2018-06-23 08:15:00"
t_int
# [1] 1529734500



回答2:


anytime author here: this is standard R and Rcpp and passing-by-SEXP behaviour: you cannot protect a SEXP being passed from being changed.

The view that anytime takes is that you are asking for an input to be converted to a POSIXct as that is what anytime does: from char, from int, from factor, from anything. As a POSIXct really is a numeric value (plus a S3 class attribute) this is what you are getting.

If you do not want this (counter to the design of anytime) you can do what @Moody_Mudskipper and @PKumar showed: used a temporary expression (or variable).

(I also think the data.table example is a little unfair as data.table -- just like Rcpp -- is very explicit about taking references where it can. So of course it refers back to the original variable. There are idioms for deep copy if you need them.)

Lastly, an obvious trick is to use format if you just want different display:

R> d <- data.frame(t_num=1529734500)
R> d[1, "posixct"] <- format(anytime::anytime(d[1, "t_num"]))
R> d
       t_num             posixct
1 1529734500 2018-06-23 01:15:00
R> 

That would work the same way in data.table, of course, as the string representation is a type change. Ditto for IDate / ITime.

Edit: And the development version in the Github repo has had functionality to preserve the incoming argument since June 2017. So the next CRAN version, whenever I will push it, will have it too.




回答3:


If you do this, it will work :

t_num <- 1529734500
anytime(t_num*1)

#> anytime(t_num*1)
#[1] "2018-06-23 06:15:00 UTC"
#> t_num
#[1] 1529734500



回答4:


Any reason to be married to anytime?

.POSIXct(t_num, tz = 'Europe/Berlin')
# [1] "2018-06-23 08:15:00 CEST"

.POSIXct(x, tz) is a wrapper for structure(x, class = c('POSIXct', 'POSIXt'), tzone = tz) (i.e. you can ignore declaring the origin), and is essentially as.POSIXct.numeric (except the latter is flexible in allowing non-UTC origin dates), look at print(as.POSIXct.numeric).




回答5:


When I did my homework before posting the question, I checked the open anytime issues. I have now browsed the closed ones as well, where I found exactly the same issue as mine:

anytime is overwriting inputs

There the package author writes:

I presume because as.POSIXct() leaves its input alone, we should too?

So from anytime version 0.3.1 (unreleased):

Numeric input is now preserved rather than silently cast to the return object type


Thus, one answer to my question is: "wait for 0.3.1"*.

When 0.3.1 is released, the behaviour of anytime(<numeric>) will agree with anytime(<non-numeric>) and as.POSIXct(<numeric>), and work-arounds not needed.


*Didn't have to wait too long: 0.3.1 is now released: "Numeric input is now preserved rather than silently cast to the return object type"



来源:https://stackoverflow.com/questions/51010539/how-to-avoid-that-anytimenumeric-updates-by-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!