我有一个由数据生成的函数,而不是多项式。对于大多数数据来说,它只有一个根,但也可以有两个根,如下图所示:
uniroot()
往往会失败,因为该函数在 h 的小值和 h 的大值(我在区间端点处使用)处具有相同的符号。
有没有办法找到 R 中函数的最大根,对于已知其参数值较大时会趋于负无穷大的函数?
作为解决方法,我将搜索间隔放置在 h 的较大值周围,即放入右侧我知道函数没有根的区域,然后使用参数
extendInt="downX"
。不过我想知道是否有更强大的东西。
根据评论的要求,这是一个可重现的示例:
# function whose largets root h is to be found
h.root <- function(x, h) {
n <- length(x)
f2 <- function(y) {
h2 <- h*h
(sum(((x-y)^2/h2 - 1) * dnorm((x-y)/h)) / (n*h*h2))^2
}
f2.int <- integrate(Vectorize(f2), -Inf, Inf)$value
(0.5 / sqrt(pi) / f2.int / n)^0.2 - h
}
# examples for problematic seeds: 45, 36
set.seed(36)
x <- rnorm(50)
h <- seq(0.05, 0.6, 0.01)
res <- h
for (i in 1:length(h)) res[i] <- h.root(x,h[i])
plot(h, res, type="l")
abline(h=0, lty=2)
print(uniroot(h.root, c(0.05, 10), x=x)$root)
也许你可以用数值方法来求解最大根
idx <- which(rowSums(sign(embed(res, 2))) == 0)
sols <- rowMeans(cbind(h[idx], h[idx + 1]))
你就得到了根(从左到右)
> sols
[1] 0.1065 0.2545 0.5525
您可以验证解决方案
> h.root(x, sols)
[1] -7.801779e-05 -1.402256e-04 -6.189450e-05
实际上,您可以对
h.root
进行矢量化并提供更高分辨率的 h
,例如,
# function whose largets root h is to be found
h.root <- Vectorize(function(x, h) {
n <- length(x)
f2 <- function(y) {
h2 <- h * h
(sum(((x - y)^2 / h2 - 1) * dnorm((x - y) / h)) / (n * h * h2))^2
}
f2.int <- integrate(Vectorize(f2), -Inf, Inf)$value
(0.5 / sqrt(pi) / f2.int / n)^0.2 - h
}, vectorize.args = "h")
# examples for problematic seeds: 45, 36
set.seed(36)
x <- rnorm(50)
h <- seq(0.05, 0.6, 1e-3)
res <- h.root(x, h)