我想使用approxfun
或类似的方法来估算曲线的函数,然后估算给定已知点x
的值给点的y
值。
这是一个简化的示例。
y <- seq(from=1, to =10, by = 1)
x <-seq(from=0.1, to =1, by = 0.1)
fun <- approxfun(x,y)
我可以使用以下命令在已知y
值的情况下近似x
值:
fun(0.65)
#[1] 6.5
但是我该如何做相反的事情,即从x
解决6.5 = approxfun(x)
?
感谢您对我最可能是愚蠢的问题的帮助。
答案 0 :(得分:0)
假设我们有一些(x, y)
数据。线性插值后,找到所有x
,以使插值的值等于y0
。
## with default value y0 = 0, it finds all roots of the interpolant
RootLinearInterpolant <- function (x, y, y0 = 0) {
if (is.unsorted(x)) {
ind <- order(x)
x <- x[ind]; y <- y[ind]
}
z <- y - y0
## which piecewise linear segment crosses zero?
k <- which(z[-1] * z[-length(z)] < 0)
## analytically root finding
xk <- x[k] - z[k] * (x[k + 1] - x[k]) / (z[k + 1] - z[k])
xk
}
更复杂的示例和测试。
set.seed(0)
x <- sort(runif(10, 0, 10))
y <- rnorm(10, 3, 1)
y0 <- 2.5
xk <- RootLinearInterpolant(x, y, y0)
#[1] 3.375952 8.515571 9.057991
plot(x, y, "l"); abline(h = y0, lty = 2)
points(xk, rep.int(y0, length(xk)), pch = 19)
## suppose that f is an interpolation function of (x, y)
## this function finds all x, such that f(x) = y0
## with default value y0 = 0, it finds all roots of the interpolant
RootNonlinearInterpolant <- function (x, y, f, y0 = 0) {
if (is.unsorted(x)) {
ind <- order(x)
x <- x[ind]; y <- y[ind]
}
z <- y - y0
k <- which(z[-1] * z[-length(z)] < 0)
nk <- length(k)
xk <- numeric(nk)
F <- function (x) f(x) - y0
for (i in 1:nk) xk[i] <- uniroot(F, c(x[k[i]], x[k[i] + 1]))$root
xk
}
尝试自然三次样条插值。
## cubic spline interpolation
f <- splinefun(x, y)
xk <- RootNonlinearInterpolant(x, y, f, y0)
#[1] 3.036643 8.953352 9.074306
curve(f, from = min(x), to = max(x))
abline(v = x, lty = 3) ## signal pieces
abline(h = y0)
points(xk, rep.int(y0, length(xk)), pch = 20)
我们看到RootNonlinearInterpolant
在第3个棋子上错过了两个交叉点。
RootNonlinearInterpolant
依赖于uniroot
,因此搜索受到更多限制。仅当y - y0
的符号在相邻结上改变时,才会调用uniroot
。显然,这并不适用于第三部分。 (在Uniroot solution in R上了解有关uniroot
的更多信息。)
还要注意,uniroot
仅返回单个根。因此,最稳定的情况是插值在棋子上是单调的,因此存在唯一根。如果实际上有多个根,uniroot
只会找到其中一个。