创建2个新变量,条件是使用R保留先前行的值

时间:2016-04-18 05:11:28

标签: r

我正在寻找能够有效生成如下所示输出的R解决方案。我可以使用retain语句和几行if-then-else逻辑等在SAS中轻松生成这个。但我找不到类似的东西 在Rforum或本网站的档案中。下面是我试图应用于生成下面的输出表的逻辑。 在任何帮助下谢谢!

如果ID是遇到的第一个ID,那么group = 1和groupdate = date,否则如果不是第一个ID和日期 - 上一个日期> 10或日期 - 上一组日期> 10然后组=前一组#+ 1和groupdate =日期或否则如果不是第一个ID和日期 - 上一个日期< = 10或日期 - 上一个组日期< = 10然后组=上一个group#和groupdate =上一个日期。

输入:

ID  DATE        ITEM
1   1/1/2014    P1
1   1/15/2014   P2
1   1/20/2014   P3
1   1/22/2014   P4
1   3/10/2015   P5
2   1/13/2015   P1
2   1/20/2015   P2
2   1/28/2015   P3
2   2/28/2015   P4
2   3/20/2015   P5

期望输出

ID  DATE        ITEM    GROUP   GROUPDATE
1   1/1/2014    P1  1   1/1/2014
1   1/15/2014   P2  2   1/15/2014
1   1/20/2014   P3  2   1/15/2014
1   1/22/2014   P4  2   1/15/2014
1   3/10/2015   P5  3   3/10/2015
2   1/13/2015   P1  1   1/13/2015
2   1/20/2015   P2  1   1/13/2015
2   1/28/2015   P3  2   1/28/2015
2   2/28/2015   P4  3   2/28/2015
2   3/20/2015   P5  4   3/20/2015

2 个答案:

答案 0 :(得分:2)

我们可以使用data.table

library(data.table)
setDT(df1)[, GROUP:={
         dt <- as.Date(DATE, "%m/%d/%Y")
         gr1 <-cumsum((dt-shift(dt, fill=dt[1L]))>10)+1L; list(gr1)} ,
            by =  ID]
df1[, GROUPDATE := DATE[1L] , by = .(GROUP, ID)]
df1
#    ID      DATE ITEM GROUP GROUPDATE
# 1:  1  1/1/2014   P1     1  1/1/2014
# 2:  1 1/15/2014   P2     2 1/15/2014
# 3:  1 1/20/2014   P3     2 1/15/2014
# 4:  1 1/22/2014   P4     2 1/15/2014
# 5:  1 3/10/2015   P5     3 3/10/2015
# 6:  2 1/13/2015   P1     1 1/13/2015
# 7:  2 1/20/2015   P2     1 1/13/2015
# 8:  2 1/28/2015   P3     1 1/13/2015
# 9:  2 2/28/2015   P4     2 2/28/2015
#10:  2 3/20/2015   P5     3 3/20/2015

答案 1 :(得分:0)

以下是另一种方法:

df <- read.table(header=T,text='ID  DATE        ITEM
               1   1/1/2014    P1
               1   1/15/2014   P2
               1   1/20/2015   P3
               1   1/22/2015   P4
               1   3/10/2015   P5
               2   1/13/2015   P1
               2   1/20/2015   P2
               2   1/28/2015   P3
               2   2/28/2015   P4
               2   3/20/2015   P5')

df$DATE <- as.Date(df$DATE,"%m/%d/%Y")

split.rows <- split.default(1:nrow(df),df$ID,drop=T)

lapply(split.rows,function(x){
split_df <- df[x,]

group <- vector('integer',length(x))
group_date <- vector('character',length(x))

group[1] <- 1
group_date[1] <- as.character(split_df[1,'DATE'])

for (i in 2:nrow(split_df)){
  if (split_df[i,'DATE'] - split_df[i-1,'DATE'] >= 10){
    group[i] <- group[i - 1] + 1
    group_date[i] <- as.character(split_df[i,'DATE'])
  }
  else{
    group[i] <- group[i - 1]
    group_date[i] <- group_date[i-1]
  }
}

df$GROUP[x] <<- group
df$GROUPDATE[x] <<- group_date

return(NULL)
})

> df
ID       DATE ITEM GROUP  GROUPDATE
1   1 2014-01-01   P1     1 2014-01-01
2   1 2014-01-15   P2     2 2014-01-15
3   1 2015-01-20   P3     3 2015-01-20
4   1 2015-01-22   P4     3 2015-01-20
5   1 2015-03-10   P5     4 2015-03-10
6   2 2015-01-13   P1     1 2015-01-13
7   2 2015-01-20   P2     1 2015-01-13
8   2 2015-01-28   P3     1 2015-01-13
9   2 2015-02-28   P4     2 2015-02-28
10  2 2015-03-20   P5     3 2015-03-20