7

我在文件中有一个字符日期时间列。我加载文件(到 a 中data.table)并执行需要将列转换为POSIXct. 然后我需要将POSIXct值写回文件,但日期时间不会相同(因为它打印不正确)。

这个打印/格式化问题是众所周知的,并且已经讨论过好几次了。我读过一些描述这个问题的帖子。我找到的最权威的答案是针对这个问题给出的。该问题的答案提供了两个应该解决此问题的函数(myformat.POSIXctform),但它们似乎不适用于此示例:

x <- "04-Jan-2013 17:22:08.139"
options("digits.secs"=6)
form(as.POSIXct(x,format="%d-%b-%Y %H:%M:%OS"),format="%d-%b-%Y %H:%M:%OS3")
[1] "04-Jan-2013 17:22:08.138"
form(as.POSIXct(x,format="%d-%b-%Y %H:%M:%OS"),format="%d-%b-%Y %H:%M:%OS4")
[1] "04-Jan-2013 17:22:08.1390"
myformat.POSIXct(as.POSIXct(x,format="%d-%b-%Y %H:%M:%OS"),digits=3)
[1] "2013-01-04 17:22:08.138"
myformat.POSIXct(as.POSIXct(x,format="%d-%b-%Y %H:%M:%OS"),digits=4)
[1] "2013-01-04 17:22:08.1390"

我的sessionInfo

R version 2.15.2 (2012-10-26)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=English_United Kingdom.1252  LC_CTYPE=English_United Kingdom.1252
[3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C                        
[5] LC_TIME=C                              

attached base packages:
[1] stats     graphics  grDevices datasets  utils     methods   base     

other attached packages:
[1] fasttime_1.0-0   data.table_1.8.9 bit64_0.9-2      bit_1.1-9
[5] sas7bdat_0.3     chron_2.3-43     vimcom_0.9-6    

loaded via a namespace (and not attached):
[1] tools_2.15.2
4

4 回答 4

5

所以我想你确实需要在我的建议中添加一些软糖因素:https ://stackoverflow.com/a/7730759/210673 。这似乎可行,但可能包括其他错误;在用于任何重要的事情之前,请仔细测试并考虑它在做什么。

myformat.POSIXct <- function(x, digits=0) {
  x2 <- round(unclass(x), digits)
  attributes(x2) <- attributes(x)
  x <- as.POSIXlt(x2)
  x$sec <- round(x$sec, digits) + 10^(-digits-1)
  format.POSIXlt(x, paste("%Y-%m-%d %H:%M:%OS",digits,sep=""))
}
于 2013-03-13T16:44:17.473 回答
4

正如您链接到的问题的答案已经说过,值的打印/格式化方式实际值不同。这只是一个印刷代表问题。

R> as.POSIXct('2011-10-11 07:49:36.3')-as.POSIXlt('2011-10-11 07:49:36.3')
Time difference of 0 secs
R> as.POSIXct('2011-10-11 07:49:36.2')-as.POSIXlt('2011-10-11 07:49:36.3')
Time difference of -0.0999999 secs

您的理解POSIXct不准确,POSIXlt不正确。您说不能将POSIXlt对象作为列包含在 data.frame 中也是不正确的。

R> x <- data.frame(date=Sys.time())
R> x$date <- as.POSIXlt(x$date)
R> str(x)
'data.frame':   1 obs. of  1 variable:
 $ date: POSIXlt, format: "2013-03-13 07:38:48"
于 2013-03-13T12:41:55.937 回答
3

当你写

我的理解是 POSIXct 表示不如 POSIXlt 表示精确

你完全错了。

两者的表示形式相同——在 Windows 上低至毫秒,在其他操作系统上低至(几乎)微秒。你读了help(DateTimeClasses)吗?

至于你的最后一个问题,是的,我的 RcppBDT 包的开发版本使用 Boost Date.Time,如果你的操作系统支持它并且你打开了正确的表示,它可以一直到纳秒。但它确实取代了 POSIXct,并且还不支持时间对象的向量。

编辑:关于您的后续问题:

R> one <- Sys.time(); two <- Sys.time(); two - one
Time difference of 7.43866e-05 secs
R>
R> as.POSIXlt(two) - as.POSIXlt(one)
Time difference of 7.43866e-05 secs
R> 
R> one    # options("digits.sec"=6) on my box
[1] "2013-03-13 07:30:57.757937 CDT"
R> 

编辑 2: 我认为您只是在体验计算机上的浮点表示是不精确的:

R> print(as.numeric(as.POSIXct("04-Jan-2013 17:22:08.138",
+                   format="%d-%b-%Y %H:%M:%OS")), digits=18)
[1] 1357341728.13800001
R> print(as.numeric(as.POSIXct("04-Jan-2013 17:22:08.139",
+                   format="%d-%b-%Y %H:%M:%OS")), digits=18)
[1] 1357341728.13899994
R> 

差异并不像您假设的那样精确为 1/1000。

于 2013-03-13T11:45:53.750 回答
3

两件事情:

1)@statquant 是正确的(而其他知名专家@Joshua Ulrich 和@Dirk Eddelbuettel 是错误的),@Aaron 在他的评论中,但这对于这里的主要问题并不重要:

POSIXlt按照设计,在存储时间方面肯定比 更准确POSIXct:由于它的秒数始终在 [0, 60) 中,因此它的粒度约为 6e-15,即 6 飞秒,比POSIXct.

但是,这在这里(和当前的 R)不是很相关:几乎所有操作,尤其是数字操作,都使用Opsgroup 方法(是的,初学者不知道,但有据可查),只需看看Ops.POSIXt 哪个确实浪费了额外的精度首先强制到POSIXct. 此外, format()/print() ing 在“.”之后使用 6 位小数。POSIXlt最多,因此也不区分POSIXct.
(由于上述原因,Dirk 和 Joshua 都导致了他们的错误断言:对于所有简单的实际用途,*lt 和 *ct 的精度是相同的)。

2)我确实倾向于同意我们(R Core)应该改进format()ing 并因此改进print()这种几分之一秒的 POSIXt 对象(仍然上面@Aaron 提到的错误修复之后)。
但是我可能是错的,并且“我们”已经做对了,根据“正确”的某种定义;-)

于 2018-08-11T15:53:35.060 回答