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

How to find decimal representation of years in R?

由于我需要以十进制格式合理准确地表示年份(〜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

可以安全地假设结束日期总是在月末,因此末尾没有闰年检查。依靠 lubridate 进行适当的 year/month 计数,我只针对开始日期调整闰年。

我发现这让我的准确度只有 3 位数 !另外,看起来有点简陋。

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

很不清楚你在这里到底想做什么,这使得准确性很难谈。

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 位才是真正重要的。

此解决方案仅使用基数 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