考虑表格
的数据框架 idnum start end var1 var2 var3 var4
1993.1 17 1993-01-01 1993-12-31 foo bar 1 2
start
且end
类型为Date
$ 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" ...
我想创建一个 new 数据框,而不是start
和end
之间每个月(包括边界)的每一行的每月观察结果:
所需输出
idnum month var1 var2 var3 var4
17 1993-01-01 foo bar 1 2
17 1993-02-01 foo bar 1 2
...
17 1993-12-01 foo bar 1 2
require(data.table) ## 1.9.2+
setDT(df)[, list(idnum=idnum, month=seq(start,end,by="month")), by=1:nrow(df)]
但是,我还有一长串额外的列,我也想跟我一起移动(除了df
,start
之外,基本上end
内的所有列。是否有一种优雅的方式提供这些额外的列?我的天真方法是用colnames(df)替换idnum = idnum,这不起作用。
更新
我按照建议尝试了(因为我希望代码对列中的顺序更改很健壮,我稍微调整了一下)
columnNames = colnames(df)[colnames(df) != 'start' & colnames(df) != 'end']
require(data.table)
test <- data.frame(df)
setDT(test)
result <- test[, list( month=seq(start,end,by="month")), by=eval(columnNames) ]
但我得到了
Error in seq.Date(start, end, by = "month") : 'from' must be of length 1
答案 0 :(得分:1)
将列放在by=list(...)
library(data.table)
df <- data.frame(idnum=17,
start=as.Date("1993-01-01"), end=as.Date("1993-12-31"),
var1="foo",var2="bar",var3=1,var4=2)
setDT(df)
result <-df[,list(month=seq(start,end,by="month")), by=list(idnum,var1,var2,var3,var4)]
head(result)
# idnum var1 var2 var3 var4 month
# 1: 17 foo bar 1 2 1993-01-01
# 2: 17 foo bar 1 2 1993-02-01
# 3: 17 foo bar 1 2 1993-03-01
# 4: 17 foo bar 1 2 1993-04-01
# 5: 17 foo bar 1 2 1993-05-01
# 6: 17 foo bar 1 2 1993-06-01
如果你有很多列并且不想枚举它们,那么这将包括除2:3以外的所有列:(使用此数据集生成相同的结果)。
result <-df[,list(month=seq(start,end,by="month")), by=eval(names(df)[-(2:3)])]