我有一个不平衡的季度面板数据集,缺少值。我希望在后续季度中从A2
中减去变量A1
。请注意,我不希望得到A2的差异,而是相互减去不同的变量。应该为每个uid单独计算差异。除了改变1999年第四季度和2000年第一季度的年份之外,其他年份也是如此。
我真的不确定我是否应该连接我的时间索引,因为像zoo这样的包只需要一个索引。但这不是问题所在。以下是一些示例数据:
structure(list(uid = c(1, 1, 1, 2, 2, 3, 3, 3), tndx = c(1999.4,
2000.1, 2000.2, 1999.4, 2000.1, 2000.1, 2000.2, 2000.3), A1 = c(2,
2, 2, 10, 11, 1, 1, 1), A2 = c(3, 3, 3, 14, 14, 2, 100, 2)), .Names = c("uid",
"tndx", "A1", "A2"), row.names = c(NA, -8L), class = "data.frame")
# which results in
uid tndx A1 A2
1 1 1999.4 2 3
2 1 2000.1 2 3
3 1 2000.2 2 3
4 2 1999.4 10 14
5 2 2000.1 11 14
6 3 2000.1 1 2
7 3 2000.2 1 100
8 3 2000.3 1 2
如果您更喜欢分离的索引,请使用以下示例:
# Thx Andrie!
x2 <- data.frame(x, colsplit(x$tndx, "\\.", names=c("year", "qtr")))
有没有一种很好的方法可以使用reshape2
,plyr
甚至是基数来解决此问题,还是您更愿意编写自定义函数?
注意,某些uid
也可能只出现一次。显然你无法计算出滞后的差异。我仍然需要检查并创建一个NA。
答案 0 :(得分:2)
我们使用uid
将其拆分为by
,并且在对单个uid
的每组行进行操作的函数中,我们创建了一个动物园对象z
,使用yearqtr
类作为索引。然后我们将时间序列与具有所有所需四分之一的空系列合并,包括给出zm
的任何缺少的中间区域,并执行给出zz
的计算。最后,我们在出路时转换为data.frame
表单:
library(zoo)
to.yearqtr <- function(x) as.yearqtr(trunc(x) + (10*(x-trunc(x))-1)/4)
DF <- do.call("rbind", by(x, x$uid, function(x) {
# columns of x are: uid tndx A1 A2
z <- zoo(x[c("A1", "A2")], to.yearqtr(x$tndx))
zm <- merge(z, zoo(, seq(start(z), end(z), 1/4)))
zz <- with(zm, cbind(zm, `A1 - A2 lag` = A1 - lag(A2, -1)))
if (ncol(zz) <= ncol(z)) zz$`A1 - A2 lag` <- NA # append NA if col not added
data.frame(uid = x[1, 1], tndx = time(zz), coredata(zz), check.names = FALSE)
}))
给出了这个:
> DF
uid tndx A1 A2 result A1 - A2 lagged
1.1 1 1999 Q4 2 3 NA NA
1.2 1 2000 Q1 2 2 NA -1
1.3 1 2000 Q2 2 3 NA 0
2.1 2 1999 Q4 2 4 NA NA
2.2 2 2000 Q1 NA NA NA NA
2.3 2 2000 Q2 NA NA NA NA
2.4 2 2000 Q3 NA NA NA NA
2.5 2 2000 Q4 NA NA NA NA
2.6 2 2001 Q1 3 4 NA NA
3.1 3 2000 Q1 1 2 NA NA
3.2 3 2000 Q2 1 NA NA -1
3.3 3 2000 Q3 1 2 NA NA
编辑:根据进一步的讨论完全重新做出解决方案。请注意,这不仅会添加额外的列,还会将索引转换为"yearqtr"
类,并添加额外缺少的行。
编辑:by
函数的一些小简化。
答案 1 :(得分:1)
我并不完全清楚你所说的是什么,因为你没有包含“正确答案”。如果你想从另一个未标记的变量中减去一个滞后变量,你可以用偏移量的索引来做到这一点。 (如果您想要将结果放回数据帧,则需要填充结果。
x$A1lagA2 <- ave(x[, c("A1", "A2")], x$uid, FUN=function(z) {
with(z, c(NA, A1[2:NROW(z)] -A2[1:(NROW(z)-1)]) ) } )[[1]]
x
uid tndx A1 A2 A1lagA2
1 1 1999.4 2 3 NA
2 1 2000.1 2 3 -1
3 1 2000.2 2 3 -1
4 2 1999.4 10 14 NA
5 2 2000.1 11 14 -3
6 3 2000.1 1 2 NA
7 3 2000.2 1 100 -1
8 3 2000.3 1 2 -99
当参数是多列时,你会发现烦人的重复额外列与ave(),但我只是拿了第一个。