创建面板数据框

时间:2014-01-08 22:26:21

标签: r panel

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

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 个答案:

答案 0 :(得分:3)

1)reshape2 创建所有年份的网格g,并将id值与rbind交叉frame

然后使用reshape2包cast frame从长到宽的格式,然后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成为一个因素,而它不在此解决方案中。

答案 1 :(得分:3)

使用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

答案 2 :(得分: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