I have a function that is data generated and not a polynomial. For most data, it only has one root, but it can also have two roots, as in in the following plot:
uniroot() tends to fail because the function has the same sign at both a small value for h and a large value for h, which I use at the interval endpoints.
Is there a way to find the greatest root of a function in R for a function that is known to go to minus infinity for large values of its argument?
As a workaround, I have placed the search interval around a large value for h, i.e. into a region on the right where I know the function has no roots, and then used the argumend extendInt="downX". I wonder however whether there is something more robust.
As requested by the comments, here is a reproducible example:
# 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)


rootSolve::uniroot.allwould do it, but if not please come back with a workable example.uniroot.alldoes is a possible approach, but far from robust. I have added code implementing the function and an example with random data whereunirootreturns the "wrong" root. Yes, in this caseuniroot.allwould work, but I am not looking for a solution that just works for normally distributed data. Maybepracma::fzerois a way (must check the reference), but maybe someone has a solution for just the problem of finding the largest root.hseq <- seq(0.05, 0.6, 0.01); s <- h.root(x, max(hseq)); for(h in rev(hseq)) if (sign(h.root(x, h)) != sign(s)) break; uniroot(\(h) h.root(x, h), c(h, 0.6))