2014-01-08 109 views
3

我想创建一个数据集的面板,每个给定的时间段都有一个观察值,这样每个单元对每个时间段都有一个新的观察值。使用下面的例子:创建一个面板数据框

id <- seq(1:4) 
year <- c(2005, 2008, 2008, 2007) 
y <- c(1,0,0,1) 
frame <- data.frame(id, year, y) 
frame 

id year y 
1 1 2005 1 
2 2 2008 0 
3 3 2008 0 
4 4 2007 1 

对于每一个唯一的ID,我想那里是2005年,2006年,2007年和2008年(此框架上下限和上限的时间段)全年独特观察,设置结果y以0为其中没有一个现有的观察所有时间,使得新的帧的样子:

id year y 
1 1 2005 1 
2 1 2006 0 
3 1 2007 0 
4 1 2008 0 
.... 
13 4 2005 0 
14 4 2006 0 
15 4 2007 1 
16 4 2008 0 

我还没有与循环很成功;任何和所有的想法将不胜感激。

回答

3

1)reshape2创建网格越过所有年份和idgframerbind它。

然后使用reshape2包castframe从长到宽的形式,然后melt它回到长形式。最后根据需要重新排列行和列。

以#结尾的行只是为了确保每年都存在,所以如果我们知道那些行可以省略的话。以##结尾的行只是重新排列行和列,所以如果没关系那行也可以省略。

library(reshape2) 

g <- with(frame, expand.grid(year = seq(min(year), max(year)), id = unique(id), y = 0)) # 
frame <- rbind(frame, g) # 

wide <- dcast(frame, year ~ id, fill = 0, fun = sum, value.var = "y") 
long <- melt(wide, id = "year", variable.name = "id", value.name = "y") 

long <- long[order(long$id, long$year), c("id", "year", "y")] ## 

,并提供:

> long 
    id year y 
1 1 2005 1 
2 1 2006 0 
3 1 2007 0 
4 1 2008 0 
5 2 2005 0 
6 2 2006 0 
7 2 2007 0 
8 2 2008 0 
9 3 2005 0 
10 3 2006 0 
11 3 2007 0 
12 3 2008 0 
13 4 2005 0 
14 4 2006 0 
15 4 2007 1 
16 4 2008 0 

2)聚合较短的解决办法是只运行与上面#结束两行,然后按照那些与aggregate如图所示。该解决方案不使用附加包。

g <- with(frame, expand.grid(year = seq(min(year), max(year)), id = unique(id), y = 0)) # 
frame <- rbind(frame, g) # 

aggregate(y ~ year + id, frame, sum)[c("id", "year", "y")] 

这给出相同的答案作为溶液(1),除了如由评议溶液注意到上述(1)使得一个id因子,而它不是在该溶液中。

+0

任何特别的原因重塑在这里?这不够吗? 'merge(frame,g,by = c(“id”,“year”),all = TRUE)'(其中'g'没有'y = 0') – Arun

+0

如果你想能够忽略如果知道所有年份都存在,则计算'g'。 –

+0

我不认为我明白,对不起。在你知道所有年份都存在的情况下,你会在哪里消除'g'的计算? – Arun

0

也许不是一个完美的解决方案,但无论如何:

df <- expand.grid(id=id, year=unique(year)) 
frame <- frame[frame$y != 0,] 
df$y <- 0 
df2 <- rbind(frame, df) 
df2 <- df2[!duplicated(df2[,c("id", "year")]),] 
df2 <- df2[order(df2$id, df2$year),] 
rownames(df2) <- NULL 
df2 
# id year y 
# 1 1 2005 1 
# 2 1 2006 0 
# 3 1 2007 0 
# 4 1 2008 0 
# 5 2 2005 0 
# 6 2 2006 0 
# 7 2 2007 0 
# 8 2 2008 0 
# 9 3 2005 0 
# 10 3 2006 0 
# 11 3 2007 0 
# 12 3 2008 0 
# 13 4 2005 0 
# 14 4 2006 0 
# 15 4 2007 1 
# 16 4 2008 0 
1

使用data.table

require(data.table) 
DT <- data.table(frame, key=c("id", "year")) 
comb <- CJ(1:4, 2005:2008) # like 'expand.grid', but faster + sets key 
ans <- DT[comb][is.na(y), y:=0L] # perform a join (DT[comb]), then set NAs to 0 
#  id year y 
# 1: 1 2005 1 
# 2: 1 2006 0 
# 3: 1 2007 0 
# 4: 1 2008 0 
# 5: 2 2005 0 
# 6: 2 2006 0 
# 7: 2 2007 0 
# 8: 2 2008 0 
# 9: 3 2005 0 
# 10: 3 2006 0 
# 11: 3 2007 0 
# 12: 3 2008 0 
# 13: 4 2005 0 
# 14: 4 2006 0 
# 15: 4 2007 1 
# 16: 4 2008 0