使用开始和结束date按date范围展开行

考虑表单的数据框

idnum start end 1993.1 17 1993-01-01 1993-12-31 1993.2 17 1993-01-01 1993-12-31 1993.3 17 1993-01-01 1993-12-31 

startendDatetypes

  $ idnum : int 17 17 17 17 27 27 $ start : Date, format: "1993-01-01" "1993-01-01" "1993-01-01" "1993-01-01" ... $ end : Date, format: "1993-12-31" "1993-12-31" "1993-12-31" "1993-12-31" ... 

我想创build一个新的数据框,而不是每个月的startend (包括边界)之间的每一个月的观察:

期望的输出

 idnum month 17 1993-01-01 17 1993-02-01 17 1993-03-01 ... 17 1993-11-01 17 1993-12-01 

我不知道month应该是什么格式,我会在某个时候想按idnum分组,其余的数据集上的回归分month

到目前为止,对于每一行, seq(from=test[1,'start'], to=test[1, 'end'], by='1 month')给了我正确的序列 – 但是只要我尝试将其应用于整个数据框,它将不起作用:

 > foo <- apply(test, 1, function(x) seq(x['start'], to=x['end'], by='1 month')) Error in to - from : non-numeric argument to binary operator 

使用data.table

 require(data.table) ## 1.9.2+ setDT(df)[, list(idnum=idnum, month=seq(start,end,by="month")), by=1:nrow(df)] 

setDTdf转换为data.table 。 然后对于每一行, by=1:nrow(df) ,我们根据需要创buildidnummonth

使用dplyr

 test %>% group_by(idnum) %>% summarize(start=min(start),end=max(end)) %>% do(data.frame(idnum=.$idnum, month=seq(.$start,.$end,by="1 month"))) 

请注意,这里我不会为每一行在startend之间生成一个序列,而是每个idnum min(start)max(end)之间的序列。 如果你想要前者:

 test %>% rowwise() %>% do(data.frame(idnum=.$idnum, month=seq(.$start,.$end,by="1 month"))) 

可能是你可以尝试:

更新

根据@Ananda Mahto的评论

  res1 <- melt(setNames(lapply(1:nrow(test), function(x) seq(test[x, "start"], test[x, "end"], by = "1 month")), test$idnum)) 

也,

  res2 <- setNames(do.call(`rbind`, with(test, Map(`expand.grid`,idnum, Map(`seq`, start, end, by='1 month')))), c("idnum", "month")) head(res1) # idnum month #1 17 1993-01-01 #2 17 1993-02-01 #3 17 1993-03-01 #4 17 1993-04-01 #5 17 1993-05-01 #6 17 1993-06-01 

tidyverse答案

数据

 df <- structure(list(idnum = c(17L, 17L, 17L), start = structure(c(8401, 8401, 8401), class = "Date"), end = structure(c(8765, 8765, 8765 ), class = "Date")), class = "data.frame", .Names = c("idnum", "start", "end"), row.names = c(NA, -3L)) 

回答和输出

 library(tidyverse) df %>% nest(start, end) %>% mutate(data = map(data, ~seq(unique(.x$start), unique(.x$end), 1))) %>% unnest(data) # # A tibble: 365 x 2 # idnum data # <int> <date> # 1 17 1993-01-01 # 2 17 1993-01-02 # 3 17 1993-01-03 # 4 17 1993-01-04 # 5 17 1993-01-05 # 6 17 1993-01-06 # 7 17 1993-01-07 # 8 17 1993-01-08 # 9 17 1993-01-09 # 10 17 1993-01-10 # # ... with 355 more rows