我对闰年有些怀疑,我如何通过使用这样的公式来确定
add.years= function(x,y){
if(!isTRUE(all.equal(y,round(y)))) stop("Argument \"y\" must be an integer.\n")
x <- as.POSIXlt(x)
x$year <- x$year+y
as.Date(x)
}
它会考虑闰年,例如在观察数据集中添加100年?我该怎么控制呢?
我有一个50年观察的时间序列数据集:
date obs
1995-01-01 1.0
1995-01-02 2.0
1995-01-03 2.5
...
2045-12-30 0.2
2045-12-31 0.1
数据集+ 100年
date obs
2095-01-01 1.0
2095-01-02 2.0
2095-01-03 2.5
...
2145-12-30 0.2
2145-12-31 0.1
经过基本检查后,我注意到原始数据集和数据集后100年的行数相同。我不确定在闰年之前的第29届Februray之前是什么,现在是3月1日非闰年的价值等等。
我可以使用 chron库函数 leap.year 检查闰年,但是我想知道是否有更简单的方法来执行此操作,确保将删除在100年后不存在的2月29日通过日期的行,并添加2月29日的新日期和NA值。
答案 0 :(得分:14)
您可以leap_year
检查一年是否为lubridate
的闰年。
years <- 1895:2005
years[leap_year(years)]
这个包也将处理2月29日不可能发生的事情。
ymd("2000-2-29") + years(1) # NA
ymd("2000-2-29") %m+% years(1) # "2001-02-28"
如@VitoshKa所述,%m+%
“添加月份”运算符会在实际日期不存在的情况下将日期回滚到上个月的末尾。
答案 1 :(得分:3)
如果出现以下情况,则一年是闰年:
这就是为什么2000年是闰年的原因(尽管它可以被100整除,它也可以被400整除)。
但一般来说,如果您有一个可以进行日期/时间计算的库,那么请使用它。进行这些计算非常复杂,容易出错,特别是涉及古代日期(日历改革)和时区。
答案 2 :(得分:1)
你的怀疑确实是对的:
x <- as.POSIXlt("2000-02-29")
y <- x
y$year <- y$year+100
y
#[1] "2100-03-01"
奇怪的是y
的其他部分保持不变,所以你不能用它们进行比较:
y$mday
#[1] 29
y$mon
#[1] 1
但您可以使用strftime
:
strftime(x,"%d")
#[1] "29"
strftime(y,"%d")
#[1] "01"
那怎么样:
add.years <- function(x,y){
if(!isTRUE(all.equal(y,round(y)))) stop("Argument \"y\" must be an integer.\n")
x.out <- as.POSIXlt(x)
x.out$year <- x.out$year+y
ifelse(strftime(x,"%d")==strftime(x.out,"%d"),as.Date(x.out),NA)
}
然后,您可以使用[
和is.na
对数据进行子集,以摆脱3月1日的重复日期。虽然这些日期似乎是连续的,但您可能需要考虑使用seq.Date
并避免丢弃数据的解决方案。
答案 3 :(得分:0)
按照DarkDust和Dirk Eddelbuettel的建议,您可以轻松滚动自己的leap_year
函数:
leap_year <- function(year) {
return(ifelse((year %%4 == 0 & year %%100 != 0) | year %%400 == 0, TRUE, FALSE))
}
并将其应用于矢量数据:
years = 2000:2050
years[leap_year(years)]
[1] 2000 2004 2008 2012 2016 2020 2024 2028 2032 2036 2040 2044 2048