如何在R中找到年份的十进制表示?

时间:2016-04-10 09:16:19

标签: r date time lubridate

由于我需要十进制格式的相当准确的年份表示(〜 4-5位的准确性会起作用),我转向了lubridate包。这就是我的尝试:

refDate <- as.Date("2016-01-10")
endDate <- as.Date("2020-12-31")
daysInLeapYear <- 366
daysInRegYear <- 365
leapYearFractStart <- 0
leapYearRegStart <- 0
daysInterval <- as.interval(difftime(endDate, refDate, unit = "d"), start = refDate)
periodObject <- as.period(daysInterval)
if(leap_year(refDate)) {
    leapYearFractStart <- (as.numeric(days_in_month(refDate))-as.numeric(format(refDate, "%d")))/daysInLeapYear
}
if(!leap_year(refDate)) {
    leapYearRegStart <- (as.numeric(days_in_month(refDate))-as.numeric(format(refDate, "%d")))/daysInRegYear
}
returnData <- periodObject@year+(periodObject@month/12)+leapYearFractStart+leapYearRegStart

可以安全地假设结束日期总是在一个月末,因此最后没有闰年检查。依靠rubridate进行适当的年/月计算,我只在开始日期调整闰年。

我认为这只能让我在 3位精度之内!此外,它看起来有点粗糙。

是否有更完整和准确的程序来确定间隔中年份的十进制表示?

2 个答案:

答案 0 :(得分:4)

目前还不清楚你在这里做了什么,这使得准确性难以谈论。

lubridate有一个函数decimal_date,可以将日期转换为小数。但是,由于3个小数位在一年内为您提供了1000个可能的位置,当我们只有365/366天时,在一天内有2到3个可行值。准确性取决于您希望结果在何时下降。

> decimal_date(as.POSIXlt("2016-01-10 00:00:01"))
[1] 2016.025
> decimal_date(as.POSIXlt("2016-01-10 12:00:00"))
[1] 2016.026
> decimal_date(as.POSIXlt("2016-01-10 23:59:59"))
[1] 2016.027

换句话说,如果你对一天中的时间感兴趣,超过3位小数只是非常重要。

答案 1 :(得分:4)

此解决方案仅使用基数R.我们使用cut(..., "year")获取年初的年份,并通过使用cut(..., "year")在下一年开始时将其与一年中的天数进行区分次年的任意日期。最后使用这些数量来获得分数并将其添加到年份。

d <- as.Date(c("2015-01-31", "2016-01-01", "2016-01-10", "2016-12-31")) # sample input

year_begin <- as.Date(cut(d, "year"))
days_in_year <- as.numeric( as.Date(cut(year_begin + 366, "year")) - year_begin )
as.numeric(format(d, "%Y")) + as.numeric(d - year_begin) / days_in_year
## [1] 2015.082 2016.000 2016.025 2016.997

或者,使用as.POSIXlt此变体将其变为一行:

with(unclass(as.POSIXlt(d)),1900+year+yday/as.numeric(as.Date(cut(d-yday+366,"y"))-d+yday))
## [1] 2015.082 2016.000 2016.025 2016.997