Ben*_*ker 17 datetime r date lubridate
我正在进行一些日期/时间操作,并在转换日期 - >时间 - >日期时遇到可解释但令人不愉快的往返问题.我已经通过在适当的点进行四舍五入来暂时克服这个问题,但我想知道是否有更好的日期处理方法会更清晰.我正在使用base-R和lubridate函数的混合.
tl; dr有一个很好的,简单的方法从十进制日期(YYYY.fff)转换到Date类(和返回)而不经过POSIXt并导致四舍五入(和可能的时区)并发症?
从1918年的几天开始,作为单独的年/月/日列(不是我的问题的关键部分,但它是我的管道恰好开始的地方):
library(lubridate)
dd <- data.frame(year=1918,month=9,day=1:12)
Run Code Online (Sandbox Code Playgroud)
转换年/月/日 - >日期 - >时间:
dd <- transform(dd,
time=decimal_date(make_date(year, month, day)))
Run Code Online (Sandbox Code Playgroud)
由于收尾,所得时间向量的连续差异并不完全是1:这是可以理解的,但会导致问题.
table(diff(dd$time)*365)
## 0.999999999985448 1.00000000006844
## 9 2
Run Code Online (Sandbox Code Playgroud)
现在假设我转换回日期:日期在午夜之前或之后(在任一方向偏离<1秒):
d2 <- lubridate::date_decimal(dd$time)
# [1] "1918-09-01 00:00:00 UTC" "1918-09-02 00:00:00 UTC"
# [3] "1918-09-03 00:00:00 UTC" "1918-09-03 23:59:59 UTC"
# [5] "1918-09-04 23:59:59 UTC" "1918-09-05 23:59:59 UTC"
# [7] "1918-09-07 00:00:00 UTC" "1918-09-08 00:00:00 UTC"
# [9] "1918-09-09 00:00:00 UTC" "1918-09-09 23:59:59 UTC"
# [11] "1918-09-10 23:59:59 UTC" "1918-09-12 00:00:00 UTC"
Run Code Online (Sandbox Code Playgroud)
如果我现在想要日期(而不是POSIXct对象)我可以使用as.Date(),但令我沮丧的是.Date()截断而不是舍入 ...
tt <- as.Date(d2)
## [1] "1918-09-01" "1918-09-02" "1918-09-03" "1918-09-03" "1918-09-04"
## [6] "1918-09-05" "1918-09-07" "1918-09-08" "1918-09-09" "1918-09-09"
##[11] "1918-09-10" "1918-09-12"
Run Code Online (Sandbox Code Playgroud)
所以差异现在是0/1/2天:
table(diff(tt))
# 0 1 2
# 2 7 2
Run Code Online (Sandbox Code Playgroud)
我可以通过先舍入来解决这个问题:
table(diff(as.Date(round(d2))))
## 1
## 11
Run Code Online (Sandbox Code Playgroud)
但我想知道是否有更好的方法(例如将POSIXct保留在我的管道中并保持日期...
正如Grothendieck和Petzoldt 在2004年的R-help服务台文章中所建议的那样:
在考虑使用哪个类时,请始终选择支持该应用程序的最不复杂的类.也就是说,
Date尽可能使用,否则使用chron和以其他方式使用POSIX类.这样的策略将大大减少错误的可能性并提高应用程序的可靠性.
本文中的扩展表显示了如何在Date,chron和POSIXct,但不包括小数时间作为候选者之一进行翻译...
如果可能的话,似乎最好避免从十进制时间转换回来.
从日期转换为十进制日期时,还需要考虑时间.由于Date没有与之相关的特定时间,因此decimal_date固有地认为它是00:00:00.
但是,如果我们只关心日期(而不是时间),我们可以假设时间成为任何东西.可以说,一天的中间(12:00:00)与一天的开始()一样好00:00:00.这将使转换Date更加可靠,因为我们不在午夜标记,几秒钟关闭不会影响输出.一要做到这一点的方法是添加12*60*60/(365*24*60*60)到dd$time
Run Code Online (Sandbox Code Playgroud)dd$time2 = dd$time + 12*60*60/(365*24*60*60) data.frame(dd[1:3], "00:00:00" = as.Date(date_decimal(dd$time)), "12:00:00" = as.Date(date_decimal(dd$time2)), check.names = FALSE) # year month day 00:00:00 12:00:00 #1 1918 9 1 1918-09-01 1918-09-01 #2 1918 9 2 1918-09-02 1918-09-02 #3 1918 9 3 1918-09-03 1918-09-03 #4 1918 9 4 1918-09-03 1918-09-04 #5 1918 9 5 1918-09-04 1918-09-05 #6 1918 9 6 1918-09-05 1918-09-06 #7 1918 9 7 1918-09-07 1918-09-07 #8 1918 9 8 1918-09-08 1918-09-08 #9 1918 9 9 1918-09-09 1918-09-09 #10 1918 9 10 1918-09-09 1918-09-10 #11 1918 9 11 1918-09-10 1918-09-11 #12 1918 9 12 1918-09-12 1918-09-12然而,应该注意,以这种方式获得的小数时间的值将是不同的.
| 归档时间: |
|
| 查看次数: |
385 次 |
| 最近记录: |