我在文件中有一个字符日期时间列。我加载文件(进入data.table
)并执行需要将列转换为POSIXct
的内容。然后我需要将POSIXct
值写回文件,但日期时间不一样(因为它打印不正确)。
此打印/格式化问题众所周知,已多次讨论过。我读过一些描述这个问题的帖子。我发现的最权威的答案都是针对this question而给出的。该问题的答案提供了两个应该解决此问题的函数(myformat.POSIXct
和form
),但它们似乎不适用于此示例:
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
答案 0 :(得分: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"
答案 1 :(得分:4)
所以我猜你确实需要在我的建议中添加一点点软糖因素: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=""))
}
答案 2 :(得分: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。
答案 3 :(得分:3)
两件事:
1)@statquant是正确的(而其他知名专家@Joshua Ulrich和@Dirk Eddelbuettel是错误的),@ Aaron在他的评论中,但这对于这里的主要问题并不重要:
通过设计 POSIXlt
绝对比POSIXct
更准确地存储时间:由于其秒始终处于[0,60),因此其粒度约为6e -15,即6飞秒,这比POSIXct
的颗粒度要小数千万倍。
但是,这在这里(以及对于当前R)不是很相关:几乎所有操作(尤其是数字操作)都使用Ops
组方法(是,初学者不知道,但有据可查),只是看一下在Ops.POSIXt
处,确实会通过首先强制到POSIXct
来浪费额外的精度。另外,format()/ print()ing在“。”之后使用6个小数。最多,因此也无法区分POSIXlt
的内部更高的精度和POSIXct
的“仅” 100纳秒的粒度。
(由于上述原因,Dirk和Joshua都得出了错误的断言:对于所有简单的实际使用,* lt和* ct的精度都是 。)
2)我确实同意我们(R Core)应该改进这种POSIXt对象的几分之一的format()
并因此print()
的改进(仍然是之后 @Aaron提到的错误修复)。
但是后来我可能是错的,并且按照“正确”的定义,“我们”正确了;-)