R 有效计算自快照日期最后一个生日起的月数(连续)

R 有效计算自快照日期最后一个生日起的月数(连续),r,plyr,lubridate,R,Plyr,Lubridate,我有一个data.frame,它包含两个日期列,一个是个人的出生日期(DOB),另一个是时间参考点(Snapshot.date),假设这是我们最后一次看到那个人的日期。还有其他列(省略),因此我理想情况下希望将结果作为列添加到现有的data.frame中 我想计算个人的上一个生日(相对于Snapshot.Date)和Snapshot.Date之间(连续)的月数 我尝试过plyr解决方案和base sapply解决方案,它们都比我预期的慢——(我需要在我的'real'data.frame中处理一百

我有一个data.frame,它包含两个日期列,一个是个人的出生日期(
DOB
),另一个是时间参考点(
Snapshot.date
),假设这是我们最后一次看到那个人的日期。还有其他列(省略),因此我理想情况下希望将结果作为列添加到现有的data.frame中

我想计算个人的上一个生日(相对于Snapshot.Date)和
Snapshot.Date
之间(连续)的月数

我尝试过plyr解决方案和base sapply解决方案,它们都比我预期的慢——(我需要在我的'real'data.frame中处理一百万行)

首先,这里是一个测试数据集。20条原始记录(2月29日的“特殊”案例,仅存在于闰年)

还有计算月份的功能(我相信这也可以改进)

对于基数为20的记录,以下是所需的输出:

       Snapshot.Date        DOB Months.Since.Birthday
32806      2015-05-31 1961-06-26            11.1643836
21294      2014-03-31 1965-01-25             2.1972603
14880      2013-07-31 1939-09-27            10.1315068
21730      2014-03-31 1952-07-14             8.5589041
17525      2013-10-31 1965-04-05             6.8547945
8516       2013-02-28 1945-06-20             8.2630137
11068      2013-04-30 1954-08-15             8.4931507
11751      2013-05-31 1969-06-11            11.6575342
2564       2012-08-31 1965-10-27            10.1315068
3832       2012-09-30 1957-09-24             0.1972603
802276     2015-06-30 1987-04-21             2.2958904
1031697    2015-06-30 1970-08-03            10.8876712
129222     2015-06-30 1962-09-12             9.5917808
588224     2015-06-30 1983-12-31             5.9863014
1093247    2015-06-30 1968-12-18             6.3945205
878037     2015-06-30 1994-07-26            11.1315068
370736     2015-06-30 1992-08-11            10.6246575
709108     2015-06-30 1985-04-25             2.1643836
861908     2015-06-30 1973-08-16            10.4602740
2199       2012-08-31 1944-02-29             6.0986301
扩展数据集以进行基准测试:

# Make 5000 records total for benchmarking, didn't replicate Feb 29th
# since it is a very rare case in the data
set.seed(1)
data.test = rbind(data.test, data.test[sample(1:19, size = 4980, replace = TRUE),])

start.time = Sys.time()
res = suppressMessages(adply(data.test , 1, transform, Months.Since.Birthday = months_since_last_birthday(Snapshot.Date, DOB)))
end.time = Sys.time()

# end.time - start.time
# Time difference of 1.793945 mins

start.time = Sys.time()
data.test$Months.Since.Birthday = suppressMessages(sapply(1:5000, function(x){return(months_since_last_birthday(data.test$Snapshot.Date[x], data.test$DOB[x]))}))
end.time = Sys.time()

# end.time - start.time
# Time difference of 1.743053 mins
我做错什么了吗?你觉得这真的很慢吗?
欢迎任何反馈

除非我遗漏了一些明显的东西,否则在
R
中有许多内置的处理时间数据的方法,特别是
base::difftime
,这可能会为您节省一些麻烦

获取上述数据集
数据。测试

data.test$dif <- round(as.vector(as.double(difftime(strptime(data.test$Snapshot.Date, format = "%Y-%m-%d"), strptime(data.test$DOB, format = "%Y-%m-%d"), units = "days"))) %% 365, 1)

data.test$dif谢谢,我会有闰年的特例。
# Make 5000 records total for benchmarking, didn't replicate Feb 29th
# since it is a very rare case in the data
set.seed(1)
data.test = rbind(data.test, data.test[sample(1:19, size = 4980, replace = TRUE),])

start.time = Sys.time()
res = suppressMessages(adply(data.test , 1, transform, Months.Since.Birthday = months_since_last_birthday(Snapshot.Date, DOB)))
end.time = Sys.time()

# end.time - start.time
# Time difference of 1.793945 mins

start.time = Sys.time()
data.test$Months.Since.Birthday = suppressMessages(sapply(1:5000, function(x){return(months_since_last_birthday(data.test$Snapshot.Date[x], data.test$DOB[x]))}))
end.time = Sys.time()

# end.time - start.time
# Time difference of 1.743053 mins
data.test$dif <- round(as.vector(as.double(difftime(strptime(data.test$Snapshot.Date, format = "%Y-%m-%d"), strptime(data.test$DOB, format = "%Y-%m-%d"), units = "days"))) %% 365, 1)
data.test$dif <- 
  round(
    as.vector(
      as.double(
        difftime(
          strptime(data.test$Snapshot.Date, format = "%Y-%m-%d"),
          strptime(data.test$DOB, format = "%Y-%m-%d"), units = "days")
        )
      )
      %% 365,
    1)