【问题标题】:Complex sequence based on a condition基于条件的复杂序列
【发布时间】:2020-08-25 15:36:21
【问题描述】:

我正在尝试将数据转换为 data2。我正在寻找基本的 R 或 dplyr 解决方案。 每个策略都有一个 ID。有开始日期和结束日期。这些都是给的。 一个保单年度从开始日期开始,一年后结束。一项政策可能会持续数年。保单的第一部分的 PolYr 值需要为 0。当保单年度进入下一年时,PolYr 的值为 1。我能够通过

Numeric sequence with condition

对于每份合约,每个 PolYr 和 CaldYr 组合都有一行。我还需要确定 CaldYr。 查看 ID = 103,我们看到合约从 2011 年开始,其第一行的 PolYr = 0 和 CaldYr = 2011。PolYr 0 的第二部分进入 2012,因此 ID = 103 的第二行将有 PolYr = 1 CaldYr = 2012。这项政策的期限超过 2 年,并在 2013 年底结束,因此它持续了五行。

以下是数据帧之前和之后的数据。 我做了一些研究,但没有发现任何我认为与我的问题相对应的东西。

library(dplyr)    
ID = c(101, rep(102, 2), rep(103,5))
    start = as.Date(c('2/1/2010', rep('5/17/2011', 2), rep('5/17/2011', 5)), '%m/%d/%Y')
    end = as.Date(c('3/5/2010', rep('1/4/2012', 2 ), rep('8/4/2013', 5 )), '%m/%d/%Y')
    data = data.frame(ID = ID, start = start, end = end)

    v = c(0,1)
    data = data %>% group_by(ID) %>% mutate(PolYr = rep_len(v, length(ID)))
    data

    data2 = data
    data2$CaldrYr = c(2010, 2011, 2012, 2011, 2012, 2012, 2013, 2013)
    data2

【问题讨论】:

  • 我不认为你已经充分展示了你的逻辑来表明需要发生什么,但你可以用data %>% group_by(ID) %>% mutate(CaldrYr = lubridate::year(start) + cumsum(PolYr)) 复制data2。也许这就是你所追求的?
  • 是的。这解决了我的问题。谢谢。

标签: r dplyr


【解决方案1】:

有了data.table,我们可以做到

library(data.table)
library(lubridate)
setDT(data)[, CaldrYr := year(start) + cumsum(PolYr), ID]

【讨论】:

  • @user2738483 它可能与year 提取或cumsum 有关,但 cumsum 是更快的选项。也许将year(start) 更改为as.integer(substr(start, 1, 4))
  • 感谢你们俩。我对这三种方法进行了计时,data.table 是最快的。然后是基础 R。然后是 dplyr。我使用 system.time data.table: 3.20 sec base R: 5.97 dplyr: 9.24 我正在处理超过 200 万行和数十万个 ID (= ContractKey) 真正的瓶颈原来是 system.time(data_res2 % group_by(ContractKey) %>% mutate(PolYr = rep_len(c(0,1), length(ContractKey)))) # user system elapsed # 924.16 673.19 1598.32 有更快的data.table解决方案吗?跨度>
  • @user2738483 ii 认为substr 方法比“年”要慢。从我对8e6 数据的实验来看,原始版本是最快的。可能是,这里的问题是cumsum
  • 第一种方法要快得多 system.time(setDT(data_res2)[, CaldrYr2 := year(SALE_DATE) + cumsum(PolYr), ContractKey]) # user system elapsed # 3.17 0.06 3.20 system. time(setDT(data_res2)[, PolYrcum := cumsum(PolYr), ContractKey ][, CaldrYr2c := as.integer(substr(SALE_DATE, 1, 4)) + PolYrcum ][, PolYrcum := NULL][]) #用户系统已过 #11.27 0.33 11.53
【解决方案2】:

在base R中,我们可以使用ave分组得到cumsum,并加上startyear值。

data$CaldrYr <- with(data, as.integer(format(start, "%Y")) + 
                            ave(PolYr, ID, FUN = cumsum))

#     ID  start      end        PolYr CaldrYr
#  <dbl> <date>     <date>     <dbl>   <dbl>
#1   101 2010-02-01 2010-03-05     0    2010
#2   102 2011-05-17 2012-01-04     0    2011
#3   102 2011-05-17 2012-01-04     1    2012
#4   103 2011-05-17 2013-08-04     0    2011
#5   103 2011-05-17 2013-08-04     1    2012
#6   103 2011-05-17 2013-08-04     0    2012
#7   103 2011-05-17 2013-08-04     1    2013
#8   103 2011-05-17 2013-08-04     0    2013

【讨论】:

    猜你喜欢
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    相关资源
    最近更新 更多