继续上一个问题,我需要将过去几年的缺失估算为R中前几年的组合。在下面的数据中,我需要将2020年估算为2019年、2018年和2017年的线性组合,并将2021年估算为2020年的组合、2019、2018。
> comb1 <- cbind(CJ(letters[1:4], 2000:2019), rnorm(80,2,1))
> comb2 <- cbind(CJ(letters[1:4], 2020:2024), data.frame(rep(NA, 20)))
> colnames(comb1) <- c("state","year","v")
> colnames(comb2) <- c("state","year","v")
>
> comb <- rbind(comb1, comb2)
> comb <- comb[order(comb$state, comb$year),]
>
我可以循环执行(如下),但由于我的数据很大(我有很多“状态”),所以速度非常慢。有人知道如何以更有效的方式做到这一点吗?
> library(dplyr)
> vlist <- unique(comb$state)
> for (i in vlist) {
> for (j in (2002:2024)) {
> value <- 0.65*comb$v[comb$year==j-1 & comb$stat==i] + 0.25*comb$v[comb$year==j-2 & comb$state==i] + 0.10*comb$v[comb$year==j-3 & comb$state==i]
> if (is.na(comb$v[comb$year==j & comb$state==i])) {
> comb$v[comb$year==j & comb$state==i] <- value
> }
> }
> }
>
我设法部分地通过向量来完成它,所以速度更快,但更优雅的解决方案会很好......
for (j in (2002:2024)) {
comb$v_1 <- ave(comb$v, comb$state, FUN = dplyr::lag)
comb$v_2 <- ave(comb$v_1, comb$state, FUN = dplyr::lag)
comb$v_3 <- ave(comb$v_2, comb$state, FUN = dplyr::lag)
comb$imp <- 0.65*comb$v_1 + 0.25*comb$v_2 + 0.10*comb$v_3
comb$v <- ifelse(is.na(comb$v)&comb$year==j, comb$imp, comb$v)
comb$v_1 <- NULL
comb$v_2 <- NULL
comb$v_3 <- NULL
comb$imp <- NULL
}
有点复杂,但是有窍门:
首先,创建一个简单的函数来根据向量的最后三个数字计算要插补的值:
impute <- function(x) {
sum(tail(x, 3) * c(0.1, 0.25, 0.65))
}
然后是另一个简单的函数,只要找到
NA
(或者只是沿着向量向前移动),就会调用此函数:
roll_impute <- function(x, y) {
if (is.na(x)) {
c(x, impute(x))
} else {
c(x, y)
}
}
现在只需使用
reduce()
包中的 purrr
即可将此函数递归地应用于 v
。 由于您希望每个 state
单独工作,因此我们预先将 data.frame
分组:
comb %>%
group_by(state) %>%
mutate(v = reduce(v, roll_impute))