在data.table中添加有条件的假人?

时间:2014-01-15 14:35:01

标签: r data.table

很抱歉这个问题很长。我会尽力澄清我的目标

我想使用更新方法在data.table中添加虚拟对象,就像this already answered in this link一样,但有点复杂。

为了更好的描述,我创建了数据。

DT <- data.table(UID = paste0("UID",rep(1:5,each=2)), 
                 date = as.IDate(c("2012-01-01","2012-01-02","2012-01-03","2012-01-04","2012-01-05","2012-01-06","2012-02-01","2012-02-02","2012-02-03","2012-02-04")),
                 value = c(1:10)) 

DT是一个data.table,包含UID,日期和值的信息。在原始数据中,结构是相同的,但具有较长的时间跨度(2年)。

这里我想根据日期添加虚拟对象。

日期有几个特殊的时间跨度,我们可以用假期代表它们。

例如,在我上面创建的假数据中。

有两个假期

  1. 从“2012-01-02”到“2012-01-05”
  2. 从“2012-02-02”到“2012-02-03”
  3. 我想添加两种类型的假人

    1. 关于假期长短的假人:首先计算不同假期的长度。在这个例子中,我们有两个不同的长度(2和4)。因此,我们将添加2个虚拟对象,表明日期是否在这些假期中。
    2. 预期结果如下:

      UID     Date    Val D_length_2  D_length_4
      UID1    1/1/2012    1   FALSE   FALSE
      UID2    1/2/2012    2   FALSE   TRUE
      UID3    1/3/2012    3   FALSE   TRUE
      UID4    1/4/2012    4   FALSE   TRUE
      UID5    1/5/2012    5   FALSE   TRUE
      UID1    1/6/2012    6   FALSE   FALSE
      UID2    2/1/2012    7   TRUE    FALSE
      UID3    2/2/2012    8   TRUE    FALSE
      UID4    2/3/2012    9   FALSE   FALSE
      UID5    2/4/2012    10  FALSE   FALSE
      
      1. 关于这一天是假期前一天,还是休假后一天的假人。
      2. UID    Date      Val    Before  After
        UID1    1/1/2012    1   TRUE    FALSE
        UID2    1/2/2012    2   FALSE   FALSE
        UID3    1/3/2012    3   FALSE   FALSE
        UID4    1/4/2012    4   FALSE   FALSE
        UID5    1/5/2012    5   FALSE   FALSE
        UID1    1/6/2012    6   FALSE   TRUE
        UID2    2/1/2012    7   TRUE    FALSE
        UID3    2/2/2012    8   FALSE   FALSE
        UID4    2/3/2012    9   FALSE   FALSE
        UID5    2/4/2012    10  FALSE   TRUE
        

        所以期望结果的总和是这样的

        UID Date    Val Before  After   D_length_2  D_length_4
        UID1    1/1/2012    1   TRUE    FALSE   FALSE   FALSE
        UID2    1/2/2012    2   FALSE   FALSE   FALSE   TRUE
        UID3    1/3/2012    3   FALSE   FALSE   FALSE   TRUE
        UID4    1/4/2012    4   FALSE   FALSE   FALSE   TRUE
        UID5    1/5/2012    5   FALSE   FALSE   FALSE   TRUE
        UID1    1/6/2012    6   FALSE   TRUE    FALSE   FALSE
        UID2    2/1/2012    7   TRUE    FALSE   FALSE   FALSE
        UID3    2/2/2012    8   FALSE   FALSE   TRUE    FALSE
        UID4    2/3/2012    9   FALSE   FALSE   TRUE    FALSE
        UID5    2/4/2012    10  FALSE   TRUE    FALSE   FALSE
        

        总观测值超过10M行,大约10个不同的假期和4个不同的长度。

        对于第二种类型的假人,我想

        f <- function(x){ 
        ifelse(x %in% as.Date(c("2012-01-02","2012-02-02")) - 1, return(TRUE), return(FALSE))
        }
        
        DT[,Before:= f(date)] 
        

        但似乎不正确。

        对于第一个,我没有提出一个好的解决方案。

        这个问题是关于data.table的更新,非常欢迎任何有关如何处理它以及如何编写更新函数的想法!

1 个答案:

答案 0 :(得分:6)

这是一个开始:

library(data.table)

DT <- data.table(UID = paste0("UID",rep(1:5,each=2)), 
                 date = as.IDate(c("2012-01-01","2012-01-02","2012-01-03","2012-01-04","2012-01-05","2012-01-06","2012-02-01","2012-02-02","2012-02-03","2012-02-04")),
                 value = c(1:10)) 
setkey(DT, date)


vacStart <- data.table(start = as.IDate(c("2012-01-02", "2012-02-02")), key="start")
vacEnd <- data.table(date = as.IDate(c("2012-01-05", "2012-02-03")), key="date")

#identify vacations:
vacStart[, Start:=.I]
DT <- vacStart[DT, roll=TRUE]
vacEnd[, End:=.I]
DT <- vacEnd[DT, roll=-Inf]
DT[,vac:=(End==Start)*Start]
DT[is.na(vac), vac:=0L]

#2-day vacations:
DT[,length_2 := (.N==2) & vac!=0, by=vac]
#days before vacation
DT[,before := c(diff(vac)>0, FALSE) & vac==0]
#           date End Start  UID value vac length_2 before
#  1: 2012-01-01   1    NA UID1     1   0    FALSE   TRUE
#  2: 2012-01-02   1     1 UID1     2   1    FALSE  FALSE
#  3: 2012-01-03   1     1 UID2     3   1    FALSE  FALSE
#  4: 2012-01-04   1     1 UID2     4   1    FALSE  FALSE
#  5: 2012-01-05   1     1 UID3     5   1    FALSE  FALSE
#  6: 2012-01-06   2     1 UID3     6   0    FALSE  FALSE
#  7: 2012-02-01   2     1 UID4     7   0    FALSE   TRUE
#  8: 2012-02-02   2     2 UID4     8   2     TRUE  FALSE
#  9: 2012-02-03   2     2 UID5     9   2     TRUE  FALSE
# 10: 2012-02-04  NA     2 UID5    10   0    FALSE  FALSE