我有一个在边界处包含NA的向量
x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
我希望结果是:
c(-3, -1, 1,-1, 1, 0, -1, 2, 5, 8)
换句话说,我想用线性插值法填充内部和边界NA(也许我不能称其为“ inter -polation”,因为NA位于边界)。
我尝试了“ zoo”包中的一个函数na.fill(x,“ extend”),但是边界输出不是我想要的东西,它只重复最左边或最右边的非NA值:
na.fill(x,"extend")
输出为
[1] -1 -1 1 -1 1 0 -1 2 2 2
我还检查了用于填充NA的其他函数,例如na.approx(),na.locf()等,但是它们都不起作用。
na.spline确实有效,但是边界NA的输出导致极大的变化。
na.spline(x)
输出为:
[1] -15.9475983 -1.0000000 1.0000000 -1.0000000 1.0000000 0.3400655 -1.0000000 2.0000000
[9] 13.1441048 35.9323144
边界点太大。谁能帮我吗?预先感谢!
答案 0 :(得分:6)
您可以使用na.spline()
库中的zoo
:
na.spline(x)
[1] 0.0 0.5 1.0 1.5 2.0 2.5
原始问题的数据:
x <- c(0, NA, 1, NA, 2, NA)
答案 1 :(得分:2)
鉴于问题编辑后的数据和预期输出,我相信以下功能可以实现。它用NA
填充内部approxfun
,然后一个个对待极端。
na.extrapol <- function(y){
x <- seq_along(y)
f <- approxfun(x[!is.na(y)], y[!is.na(y)])
y[is.na(y)] <- f(x[is.na(y)])
r <- rle(is.na(y))
if(r$values[1]){
Y <- y[r$lengths[1] + 1:2]
X <- seq_len(r$lengths[1])
y[rev(X)] <- Y[1] - diff(Y)*X
}
n <- length(r$lengths)
if(r$values[n]){
s <- sum(r$lengths[-n])
Y <- y[s - 1:0]
X <- seq_len(r$lengths[n])
y[s + X] <- Y[2] + diff(Y)*X
}
y
}
x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
na.extrapol(x)
#[1] -3 -1 1 -1 1 0 -1 2 5 8
x2 <- c(NA, NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
na.extrapol(x2)
#[1] -5 -3 -1 1 -1 1 0 -1 2 5 8
答案 2 :(得分:2)
这是一种实现方法:
首先,我们进行线性逼近,这将使我们从左到右拥有所有 tail NA
-s:
x <- na.approx(x, method = "constant", f = 0.5,na.rm = F)
现在让我们找到非NA向量以及相关的最左和最右算术级数增量项:
x_c <- x[!is.na(x)]
left <- x_c[1] - x_c[2]
right <- x_c[length(x_c)] - x_c[length(x_c) - 1]
现在是时候用算术级数获得的数字向左右NA
-s填充:
ind_x<- which(!is.na(x))
big_M <- 100
x[(ind_x[length(ind_x)]):length(x)] <- seq(x[ind_x[length(ind_x)]],
sign(right) * big_M,
right)[1:(length(x) - ind_x[length(ind_x)] + 1)]
x[ind_x[1]:1] <- seq(x[ind_x[1]],sign(left) * big_M,left)[1:ind_x[1]]
y <- x
其中big_M
是用户定义的大数,给定基础数据,则算术级数不会超过该数字。
输入-输出:
x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
> y
[1] -3 -1 1 -1 1 0 -1 2 5 8
x <- c(NA,NA,NA, -1, 1,-1, 1, NA, -1, 2, NA, NA,NA)
> y
[1] -7 -5 -3 -1 1 -1 1 0 -1 2 5 8 11
x <- c(NA,NA,NA, 5,1, 1,-1, 1, NA, -1, 2, NA, NA,NA)
> y
[1] 17 13 9 5 1 1 -1 1 0 -1 2 5 8 11
答案 3 :(得分:0)
除了考虑Hmisc::approxExtrap
之外,另一种选择是使用lm
,但它很可能会比这里的其他选项慢
x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
DF <- data.frame(i=seq_along(x), x)
cc <- DF[complete.cases(DF),]
DF$x <- approx(cc$i, cc$x, DF$i)$y
hh <- head(cc, 2L)
tt <- tail(cc, 2L)
DF$x[DF$i < hh$i[1L]] <- predict(lm(x ~ i, hh), DF[DF$i < hh$i[1L], "i", drop=FALSE])
DF$x[DF$i > tt$i[2L]] <- predict(lm(x ~ i, tt), DF[DF$i > tt$i[2L], "i", drop=FALSE])
DF
输出:
i x
1 1 -3
2 2 -1
3 3 1
4 4 -1
5 5 1
6 6 0
7 7 -1
8 8 2
9 9 5
10 10 8