使用data.table扩展数据框

时间:2014-07-22 14:15:23

标签: r dataframe data.table

考虑表格

的数据框架
       idnum      start        end var1 var2 var3 var4 
1993.1    17 1993-01-01 1993-12-31  foo  bar    1    2 

startend类型为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 数据框,而不是startend之间每个月(包括边界)的每一行的每月观察结果:

所需输出

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

我是suggested

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

但是,我还有一长串额外的列,我也想跟我一起移动(除了dfstart之外,基本上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

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)])]