获取日期之间的年份差异(浮点数)

53

我想根据基准日期和测量日期之间的差异以及源半衰期(以年为单位)来纠正源活度。假设我有

ref_date <- as.Date('06/01/08',format='%d/%m/%y')

并且我的数据框中有一个与日期格式相同的列,例如,

today <- as.Date(Sys.Date(), format='%d/%m/%y')

我可以使用 lubridate 包来找到这些日期之间的年数。

year(today)-year(ref_date)
[1] 5

例如,是否有一个函数可以获得浮点数答案 today - ref_date = 5.2年?

有没有一个函数可以用来得到浮点数答案 today - ref_date = 5.2y,例如?

7个回答

70

当然可以,使用difftime()函数并将结果转换为数字格式:

R> as.numeric(difftime(as.Date("2003-04-05"), as.Date("2001-01-01"), 
+                      unit="weeks"))/52.25
[1] 2.2529
R> 
注意,我们必须转换为以52.25为比例的周,因为在计算年份时存在一些不确定性---2月29日每4年会出现一次,但不是每100年等等。所以你必须定义它。difftime() 可以处理所有时间单位,直到周为止。由于“分子”不是恒定的,月份无法完成相同的操作。

1
谢谢。我认为我可以除以365.25而省略“unit=weeks”。 - moadeep
1
不,你需要--只需尝试一下就可以看到。该单位会自动调整,请使用小于一的增量进行尝试,甚至可以使用POSIXct对象(例如来自Sys.time())。 - Dirk Eddelbuettel
一年中的周数总是相同的吗? - sop
3
52.25*7=365.75。维基百科称公历一年有365.2425天,365.2425/7=52.1775。如何正确计算呢? - sop

52

lubridate 包含一个内置函数time_length,可以帮助执行这个任务。

time_length(difftime(as.Date("2003-04-05"), as.Date("2001-01-01")), "years")
[1] 2.257534

time_length(difftime(as.Date("2017-03-01"), as.Date("2012-03-01")),"years")
[1] 5.00274

您可以在此处找到lubridate软件包的文档。


2
请注意下面@RenMa的答案,使用difftime()可能会导致不正确的结果。我在查看1948-12-07和今天(2018-11-29)之间的差异时注意到了这一点,通过difftime()是70.02466,而通过interval()是69.97808。 start <- as.Date("1948-12-07"); end <- as.Date("2018-11-29"); difftime(end, start) %>% time_length(unit = "years"); interval(start, end) %>% time_length(unit = "years") - Ilari Scheinin

24

Bryan F启发,如果使用间隔对象,time_length()函数将更有效。

time_length(interval(as.Date("2003-04-05"), as.Date("2001-01-01")), "years")
[1] -2.257534
time_length(difftime(as.Date("2017-03-01"), as.Date("2012-03-01")),"years")
[1] 5.00274
time_length(interval(as.Date("2017-03-01"), as.Date("2012-03-01")),"years")
[1] -5

如果您使用interval()获取时间差并将其传递给time_length()time_length()会考虑到不是所有月份和年份都有相同数量的天数,例如闰年。

为什么在计算时间长度后会得到一个负号? - Ray
2
interval(start_date, end_date) 基本上是使用 end_date 减去 start_date。因此,如果您的 start_date 在 end_date 之后发生,则间隔将为负数。 - Ren Ma

6

虽然不是对你问题的确切回答,但在某些情况下,来自Dirk Eddelbuettel的答案可能会产生一些小错误。

请考虑以下示例:

as.numeric(difftime(as.Date("2012-03-01"), as.Date("2017-03-01"), unit="weeks"))/52.25
[1] -4.992481

正确答案应该至少是5年。

以下函数(使用 lubridate 包)将计算两个日期之间的完整年数:

# Function to calculate an exact full number of years between two dates
year.diff <- function(firstDate, secondDate) {
  yearsdiff <- year(secondDate) - year(firstDate)
  monthsdiff <- month(secondDate) - month(firstDate)
  daysdiff <- day(secondDate) - day(firstDate)

  if ((monthsdiff < 0) | (monthsdiff == 0 & daysdiff < 0)) {
    yearsdiff <- yearsdiff - 1
  }

  yearsdiff
}

您可以根据您定义的上一个(未完成)年份的天数来修改它以计算小数部分。


1
您可以使用包BondValuation中的函数AnnivDates()
R> library('BondValuation')
R> DateIndexes <- unlist(
+   suppressWarnings(
+     AnnivDates("2001-01-01", "2003-04-05", CpY=1)$DateVectors[2]
+     )
+   )
R> names(DateIndexes) <- NULL
R> DateIndexes[length(DateIndexes)] - DateIndexes[1]
[1] 2.257534

点击这里获取BondValuation包的文档。


0

要获取年份差异(浮点数),您可以将日期转换为年份的十进制数,然后计算它们之间的差异。

#Example Dates
x <- as.Date(c("2001-01-01", "2003-04-05"))

#Convert Date to decimal year:
date2DYear <- function(x) {
  as.numeric(format(x,"%Y")) + #Get Year an add
    (as.numeric(format(x,"%j")) - 0.5) / #Day of the year divided by
    as.numeric(format(as.Date(paste0(format(x,"%Y"), "-12-31")),"%j")) #days of the year
}
diff(date2DYear(x)) #Get the difference in years
#[1] 2.257534

我从一年的天数减去0.5,因为不确定你是在一天的开始还是结束,并且%j以1开始。
我认为2012-03-01和2017-03-01之间的差距不需要是5年,因为2012年有366天,2017年有365天,而2012-03-01是一年中的第61天,2017-03-01是第60天。
x <- as.Date(c("2012-03-01", "2017-03-01"))
diff(date2DYear(x))
#[1] 4.997713

请注意,使用来自lubridatetime_lengthinterval在进行累积时间差时不一定会得到相同的结果。
library(lubridate)

x <- as.Date(c("2012-01-01", "2012-03-01", "2012-12-31"))
time_length(interval(x[1], x[3]), "years")
#[1] 0.9972678
time_length(interval(x[1], x[2]), "years") +
 time_length(interval(x[2], x[3]), "years")
#[1] 0.9995509 #!
diff(date2DYear(x[c(1,3)]))
#[1] 0.9972678
diff(date2DYear(x[c(1,2)])) + diff(date2DYear(x[c(2,3)]))
#[1] 0.9972678

x <- as.Date(c("2013-01-01", "2013-03-01", "2013-12-31"))
time_length(interval(x[1], x[3]), "years")
#[1] 0.9972603
time_length(interval(x[1], x[2]), "years") +
 time_length(interval(x[2], x[3]), "years")
#[1] 0.9972603
diff(date2DYear(x[c(1,3)]))
#[1] 0.9972603
diff(date2DYear(x[c(1,2)])) + diff(date2DYear(x[c(2,3)]))
#[1] 0.9972603

-1

既然您已经在使用lubridate包,那么您可以使用一个简单的技巧来获得浮点数中的年数:

找到一年中的秒数:

seconds_in_a_year <- as.integer((seconds(ymd("2010-01-01")) - seconds(ymd("2009-01-01"))))

现在获取您想要的两个日期之间的秒数

seconds_between_dates <- as.integer(seconds(date1) - seconds(date2))

你的浮点数年数最终答案为

years_between_dates <- seconds_between_dates / seconds_in_a_year 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接