如何使用lubridate包计算两个日期向量之间的月数,其中一个向量具有NA值?

时间:2014-08-18 18:31:03

标签: r

我已经阅读了lubridate软件包手册,并查询了Stack Overflow的各种问题,但是对我的具体问题没有答案。

我尝试做的是计算出事件发生时间与出生日期和特定事件日期之间的差异。

因此,我使用sas7bdat包导入了SAS数据集,并使用以下代码将我的SAS日期变量(DOB和Event)转换为R对象:

df$DOB <- as.Date(df$DOB, origin="1960-01-01")
df$DOB1 <- ymd(df$DOB)

Event变量也是如此:

df$Event <- as.Date(df$Event, origin="1960-01-01")
df$Event1 <- ymd(df$Event)

但是,DOB有一些NA值。因此,对于以下代码,我想用它来计算年龄(以月为单位)。

df$interval <- new_interval(df$DOB1,df$Event1)
df$Age1 <- df$interval %/% months(1)

我收到错误:

  

est [start + \ test * per&lt;结束]&lt; - est [start + est * per&lt;结束] +:订阅作业中不允许使用NA

我做错了什么?我尝试了if / else函数,但可能使用不正确。

(注意:对于那里的SAS程序员,我试图产生与以下函数相同的结果:

IF DOB ne . THEN Tage=Floor(intck('month',DOB,Event)-(Day(Event)<Day(DOB)));

4 个答案:

答案 0 :(得分:19)

使用lubridate包的简单示例

library(lubridate)
date1='20160101'
date2='20160501'
x=interval(ymd(date1),ymd(date2))
x= x %/% months(1)
print(x)
# answer : 4

或以下是相同的:

x=as.period(x) %>% month()
print(x)
# answer : 4

答案 1 :(得分:4)

那么,我对这位才华横溢的工作同事的回答表示赞赏。我忽略了包含一个可重复的例子,因为每当我写一个简单的问题近似值时,df$Age1 <- df$interval %/% months(1)总是有效!这让我完全难过。直到我在我的650,000+生日和事件日期的数据框架上运行代码时才出现错误消息......

Error in est[start + est * per < end] <- est[start + est * per < end] + : NAs are not allowed in subscripted assignments

......甚至会出现!我的同事有想法使用以下函数迭代地处理这个计算:

df$Age1 = rep(NA, nrow(df))
for (i in 1:nrow(df)) {
   df$Age1[i]<- df$interval[i] %/% months(1)
                      }
df$Age1[1:15]

使用我的数据框,很明显看到这个计算挂在了第13行!

> df$interval[13]
[1] 1995-10-31 19:00:00 EST--1996-05-26 20:00:00 EDT

所以我们不确定,但也许df$DOB[13]是10/31的事实正在搞砸它。之前已经报告了lubridate包的这类问题(即,lubridate无法将间隔除以其中一个日期在月末的时间段):

https://github.com/hadley/lubridate/issues/235

我们找到解决方案的方法是使用as.period然后将其转换为月份:

df$Age1<- as.period(df$interval)
head(df$Age1)

[1] "1y 2m 26d 0H 0M 0S" "6m 15d 23H 0M 0S"  
[3] "4m 9d 23H 0M 0S"    "3m 19d 23H 0M 0S"  
[5] "3y 0m 25d 0H 0M 0S" "1y 1m 29d 1H 0M 0S"

df$Age1 <- df$Age1 %/% months(1)
head(df$Age1)

[1] 14  6  4  3 36 13

答案 2 :(得分:4)

以下是lubridate(1.3.3)报告此问题的另一个例子。请注意,可能会有不同的错误消息,具体取决于数据集中的其他内容,问题似乎取决于度量单位(在我的情况下,工作月数,而年份没有)。

dat <- as.data.frame(list(Start = as.Date(c("1942-08-09", "1956-02-29")),
                          End   = as.Date(c("2007-07-31", "2007-09-13"))))

int0 <- with(dat, new_interval(Start, End))
as.period(int0, unit = "years")
"Error in est[start + est * per > end] <- est[start + est * per > end] -  : 
  NAs are not allowed in subscripted assignments"

int1 <- with(dat[1,], new_interval(Start, End))
as.period(int1, unit = "years")
[1] "64y 11m 22d 0H 0M 0S"

int2 <- with(dat[2,], new_interval(Start, End))
as.period(int2, unit = "years")
"Error in while (any(start + est * per > end)) est[start + est * per >  : 
  missing value where TRUE/FALSE needed"

as.period(int0) %/% years(1)
[1] 64 51

as.period(int0, unit = "months")
[1] "779m 22d 0H 0M 0S" "618m 15d 0H 0M 0S"

答案 3 :(得分:2)

而不是

df$Age1 <- df$interval %/% months(1)

你可以尝试:

df$Age1 <- NA
df$Age1[!is.na(df$DOB)] <- df$interval[!is.na(df$DOB)] %/% months(1)