The command density()
, although very useful for a quick inspection of the KDE, is also very restrictive since it only returns the values on a grid. I prefer to code my own KDE (usually with a Gaussian kernel). This can be obtained as shown below (1-line code):
rm(list=ls())
# Constructing your own KDE
set.seed(123)
sample = rnorm(1000,10,1)
# Bandwidth used by density()
hT = bw.nrd0(sample)
kde <- Vectorize(function(x) mean(dnorm((x-sample)/hT)/hT))
# Comparison
plot(density(sample))
curve(kde,6,13,add=T,col="red")
The corresponding nonparametric estimator of the CDF can be obtained as follows:
# Obtaining the corresponding kernel distribution estimator
KDE <- Vectorize(function(x) mean(pnorm((x-sample)/hT)))
curve(KDE,6,13,col="blue")
Using these functions, you can manually approximate the percentiles if you can provide an interval where the quantile of interest lies:
# Manual calculation of the percentile (requires the probability and an interval containing the quantile)
QKDE <- function(p,Interval){
tempf <- function(t) KDE(t)-p
return(uniroot(tempf,Interval)$root )
}
QKDE(0.5,c(8,12))
This may not be the most efficient way, but it works, and it is fast and accurate. I hope this helps.