Получить разницу дат в годах (с плавающей запятой)
Я хочу исправить исходную активность на основе разницы между датой отсчета и даты измерения и периодом полужизни источника (измеряется в годах). Скажем, у меня
ref_date <- as.Date('06/01/08',format='%d/%m/%y')
и столбец в моем data.frame
с тем же самым форматом даты, например,
today <- as.Date(Sys.Date(), format='%d/%m/%y')
Я могу найти количество лет между этими датами, используя пакет lubridate
year(today)-year(ref_date)
[1] 5
Есть ли функция, которую я могу использовать для получения ответа с плавающей запятой today - ref_date
= 5.2y, например?
Ответы
Ответ 1
Да, конечно, используйте 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, так как есть немного двусмысленности
там с точки зрения подсчета лет --- 29 февраля происходит каждые 4 года, но не каждый 100-й и т.д.
Итак, вы должны это определить. difftime()
обрабатывает все единицы времени до нескольких недель. Месяцы не могут быть выполнены по той же причине непостоянного "числителя".
Ответ 2
Пакет 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 можно найти здесь.
Ответ 3
Вдохновленный Брайаном Ф., 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()
учитывает тот факт, что не все месяцы и годы имеют одинаковое количество дней, например високосный год,
Ответ 4
Неточный ответ на ваш вопрос, но ответ от 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
}
Вы можете изменить его, чтобы вычислить дробную часть в зависимости от того, как вы определяете количество дней в последний (не законченный) год.
Ответ 5
Вы можете использовать функцию AnnivDates()
пакета BondValuation:
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.
Ответ 6
Поскольку вы уже используете пакет 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