使用 R 在面板中插值高于最大值的数据

Interpolating data above the maximum value in a panel with R

我有一个包含缺失值的面板,我需要对其进行插值。

a <- data.frame(id= c(1,1,1,1,1,1,1,2,2,2,2,2,2,2), year=1:7, index=c(1,NA,NA,NA,3,NA,NA, 2,NA,NA,NA,5,NA,NA))

问题是我没有最终值,所以我想使用相同的插值线来预测高于上次报告的观测值的值。此外,插值应该是“按 id”,而不是将下一个 id 的第一个观察结果视为该行的一部分。

我已经尝试了基本插值,但它确实在最新值处停止,或者使用下一个 id 进行预测:

a <- na.approx(a)

我得到的输出:

       id year    index
 [1,]  1    1 1.000000
 [2,]  1    2 1.500000
 [3,]  1    3 2.000000
 [4,]  1    4 2.500000
 [5,]  1    5 3.000000
 [6,]  1    6 2.666667
 [7,]  1    7 2.333333
 [8,]  2    1 2.000000
 [9,]  2    2 2.750000
[10,]  2    3 3.500000
[11,]  2    4 4.250000
[12,]  2    5 5.000000
[13,]  2    6       NA
[14,]  2    7       NA

期望的输出:

        id year    index
 [1,]  1    1 1.000000
 [2,]  1    2 1.500000
 [3,]  1    3 2.000000
 [4,]  1    4 2.500000
 [5,]  1    5 3.000000
 [6,]  1    6 3.500000
 [7,]  1    7 4.000000
 [8,]  2    1 2.000000
 [9,]  2    2 2.750000
[10,]  2    3 3.500000
[11,]  2    4 4.250000
[12,]  2    5 5.000000
[13,]  2    6 5.750000
[14,]  2    7 6.500000
    

使用 lm,您可以获得此简单插值所使用的斜率,然后使用该斜率通过 predict 生成新值。但也许有更简单的解决方案

mod <- lm(index ~ year, a)

a[,2] <- predict(mod, newdata=data.frame(year=a$year))

编辑 1

不,对于每个 id 我们将 运行 一个不同的 lm。为此,我们 select a 的部分在循环中具有唯一的 id,而 运行 lm 仅包含该部分:

for(i in unique(a$id)){
  ai = a[a$id==i,]
  mod = lm(index ~ year, ai)
  a[a$id==i,3] = predict(mod, newdata=data.frame(year=ai$year))}

这个有用吗:

library(dplyr)
library(tidyr)
library(purrr)
a %>% mutate(index = replace_na(index, 0)) %>% 
      mutate(index = accumulate(index, ~ .5 + .x))
  year index
1    1   1.0
2    2   1.5
3    3   2.0
4    4   2.5
5    5   3.0
6    6   3.5
7    7   4.0
> 

看起来这些值遵循线性模式。然后您可以使用 fit=lm(index~year, data=a) 然后使用 a$index=fit$coef[2]*a$year+fit$coef[1].

预测值

假设根据评论从问题中修改了以下数据,我们定义了一个函数,如果所有 index 值都是 NA,则 returns NA 否则 na.spline 和然后按 id 应用它:

library(zoo)

a <- data.frame(id= c(1,1,1,1,1,1,1,2,2,2,2,2,2,2), year=1:7, 
  index=c(NA,NA,NA,NA,NA,NA,NA, 2,NA,NA,NA,5,NA,NA))

na_spline <- function(x) if (all(is.na(x))) NA else na.spline(x)
transform(a, index = ave(index, id, FUN = na_spline))
##    id year index
## 1   1    1    NA
## 2   1    2    NA
## 3   1    3    NA
## 4   1    4    NA
## 5   1    5    NA
## 6   1    6    NA
## 7   1    7    NA
## 8   2    1  2.00
## 9   2    2  2.75
## 10  2    3  3.50
## 11  2    4  4.25
## 12  2    5  5.00
## 13  2    6  5.75
## 14  2    7  6.50