使用开始和结束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
start
和end
的Date
types
$ 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一个新的数据框,而不是每个月的start
和end
(包括边界)之间的每一个月的观察:
期望的输出
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)]
setDT
将df
转换为data.table
。 然后对于每一行, by=1:nrow(df)
,我们根据需要创buildidnum
和month
。
使用dplyr
:
test %>% group_by(idnum) %>% summarize(start=min(start),end=max(end)) %>% do(data.frame(idnum=.$idnum, month=seq(.$start,.$end,by="1 month")))
请注意,这里我不会为每一行在start
和end
之间生成一个序列,而是每个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