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

mcj*_*udd 11 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)
Run Code Online (Sandbox Code Playgroud)

和Event变量一样:

df$Event <- as.Date(df$Event, origin="1960-01-01")
df$Event1 <- ymd(df$Event)
Run Code Online (Sandbox Code Playgroud)

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

df$interval <- new_interval(df$DOB1,df$Event1)
df$Age1 <- df$interval %/% months(1)
Run Code Online (Sandbox Code Playgroud)

我收到错误:

est [start +\test*per <end] < - est [start +\test*per <end] +中的错误:下标作业中不允许使用NA

我究竟做错了什么?我尝试过if/else函数,但可能使用不当.

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

IF DOB ne . THEN Tage=Floor(intck('month',DOB,Event)-(Day(Event)<Day(DOB)));
Run Code Online (Sandbox Code Playgroud)

hyu*_*ong 23

使用lubridate包的简单示例

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

或以下是相同的:

x=as.period(x) %>% month()
print(x)
# answer : 4
Run Code Online (Sandbox Code Playgroud)

  • `%/%` 有什么作用?那是 lubridate 包的一部分吗? (3认同)
  • 如果间隔 &gt; 12 个月,则第二种解决方案可能会导致错误答案。本质上,它会将其读作“y”年、“m”个月...”并返回“m 个月”,而正确答案应该是“y*12 + m”。 (3认同)

mcj*_*udd 6

好吧,我将这个答案归功于我的才华横溢的同事。我忽略了一个可重复的例子,因为只要我写一个简单的问题近似值,就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]
Run Code Online (Sandbox Code Playgroud)

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

> df$interval[13]
[1] 1995-10-31 19:00:00 EST--1996-05-26 20:00:00 EDT
Run Code Online (Sandbox Code Playgroud)

因此我们不确定,但也许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
Run Code Online (Sandbox Code Playgroud)


JWi*_*man 6

这是所报告的 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"
Run Code Online (Sandbox Code Playgroud)