填写r中数据帧的时间间隔

时间:2015-02-24 20:04:35

标签: r dataframe

我有一个包含以下信息的数据集:

id     class     year     n
25     A63      2006      3
25     F16      2006      1
39     0901      2001     1
39     0903      2001     3
39     0903      2003     2
39     1901      2003     1
...

大约有10万个不同的ID和超过300个类。这一年从1998年到2007年各不相同。

我想要做的是,在发生一些id和类之后填补时间间隔,id和class为n = 0。

然后计算n的总和和类的数量。

例如,上述6行数据应扩展到下表:

id     class     year     n  sum  Qc  Qs
25     A63      2006      3  3    2   2
25     F16      2006      1  1    2   2
25     A63      2007      0  3    0   2
25     F16      2007      0  1    0   2
39     0901      2001     1  1    2   2
39     0903      2001     3  3    2   2
39     0901      2002     0  1    0   2
39     0903      2002     0  3    0   2
39     0901      2003     0  1    2   3
39     0903      2003     2  5    2   3
39     1901      2003     1  1    2   3
39     0901      2004     0  1    0   3
39     0903      2004     0  5    0   3
39     1901      2004     0  1    0   3
...
39     0901      2007     0  1    0   3
39     0903      2007     0  5    0   3
39     1901      2007     0  1    0   3

我可以通过丑陋的for循环解决它,它需要一个小时才能得到结果。有没有更好的方法呢?矢量化或使用data.table?

2 个答案:

答案 0 :(得分:0)

使用expand.grid获取cartesian product of class and year

然后merge您当前的数据框到这个新数据框。然后做经典子集替换。

df <- data.frame(class = as.factor(c("A63","F16","0901","0903","0903","1901")),
                year = c(2006,2006,2001,2001,2003,2003),
                n=c(3,1,1,3,2,1))

df2 <- expand.grid(class = levels(df$class),
                   year= 1997:2006)

df2 <- merge(df2,df, all.x=TRUE)
df2$n[is.na(df2$n)] <- 0

答案 1 :(得分:0)

使用dplyr您可以尝试:

library(dplyr)
df%>% group_by(class,id) %>% arrange(year) %>%
    do(merge(data.frame(year=c(.$year[1]:2007),id=rep(.$id[1],2007-.$year[1]+1),class=rep(.$class[1],2007-.$year[1]+1)),.,all.x=T))

它按类和ID对数据进行分组,并将每个组合并到一个数据框中,该数据框包含具有该组的ID和类的所有年份。

编辑:如果您只想在某个id之后执行此操作:

  as.data.frame(rbind(df[df$id<=25,],df%>% filter(id>25) %>% group_by(class,id) %>% arrange(year) %>%
        do(merge(data.frame(year=c(.$year[1]:2007),id=rep(.$id[1],2007-.$year[1]+1),class=rep(.$class[1],2007-.$year[1]+1)),.,all.x=T))))