使用 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
我有一个包含缺失值的面板,我需要对其进行插值。
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