Una manera simple es rasterizar el dominio de integración y calcular una aproximación discreta a la integral.
Hay algunas cosas a tener en cuenta:
Asegúrese de cubrir más que la extensión de los puntos: debe incluir todas las ubicaciones donde la estimación de densidad del núcleo tendrá valores apreciables. Esto significa que necesita expandir la extensión de los puntos entre tres y cuatro veces el ancho de banda del núcleo (para un núcleo gaussiano).
El resultado variará un poco con la resolución del ráster. La resolución debe ser una pequeña fracción del ancho de banda. Debido a que el tiempo de cálculo es proporcional al número de celdas en el ráster, casi no se necesita tiempo adicional para realizar una serie de cálculos con resoluciones más gruesas que la prevista: verifique que los resultados para los más gruesos converjan en el resultado para La mejor resolución. Si no lo son, puede ser necesaria una resolución más fina.
Aquí hay una ilustración para un conjunto de datos de 256 puntos:
Los puntos se muestran como puntos negros superpuestos en dos estimaciones de densidad del núcleo. Los seis puntos rojos grandes son "sondas" en las que se evalúa el algoritmo. Esto se ha hecho para cuatro anchos de banda (un valor predeterminado entre 1.8 (verticalmente) y 3 (horizontalmente), 1/2, 1 y 5 unidades) con una resolución de 1000 por 1000 celdas. La siguiente matriz de diagrama de dispersión muestra cuán fuertemente dependen los resultados del ancho de banda para estos seis puntos de sonda, que cubren una amplia gama de densidades:
La variación ocurre por dos razones. Obviamente, las estimaciones de densidad difieren, introduciendo una forma de variación. Más importante aún, las diferencias en las estimaciones de densidad pueden crear grandes diferencias en cualquier punto único ("sonda"). La última variación es mayor en torno a las "franjas" de densidad media de los grupos de puntos, exactamente aquellos lugares donde es probable que este cálculo sea el más utilizado.
Esto demuestra la necesidad de una precaución sustancial al usar e interpretar los resultados de estos cálculos, ya que pueden ser muy sensibles a una decisión relativamente arbitraria (el ancho de banda a usar).
Código R
El algoritmo está contenido en la media docena de líneas de la primera función f
,. Para ilustrar su uso, el resto del código genera las figuras anteriores.
library(MASS) # kde2d
library(spatstat) # im class
f <- function(xy, n, x, y, ...) {
#
# Estimate the total where the density does not exceed that at (x,y).
#
# `xy` is a 2 by ... array of points.
# `n` specifies the numbers of rows and columns to use.
# `x` and `y` are coordinates of "probe" points.
# `...` is passed on to `kde2d`.
#
# Returns a list:
# image: a raster of the kernel density
# integral: the estimates at the probe points.
# density: the estimated densities at the probe points.
#
xy.kde <- kde2d(xy[1,], xy[2,], n=n, ...)
xy.im <- im(t(xy.kde$z), xcol=xy.kde$x, yrow=xy.kde$y) # Allows interpolation $
z <- interp.im(xy.im, x, y) # Densities at the probe points
c.0 <- sum(xy.kde$z) # Normalization factor $
i <- sapply(z, function(a) sum(xy.kde$z[xy.kde$z < a])) / c.0
return(list(image=xy.im, integral=i, density=z))
}
#
# Generate data.
#
n <- 256
set.seed(17)
xy <- matrix(c(rnorm(k <- ceiling(2*n * 0.8), mean=c(6,3), sd=c(3/2, 1)),
rnorm(2*n-k, mean=c(2,6), sd=1/2)), nrow=2)
#
# Example of using `f`.
#
y.probe <- 1:6
x.probe <- rep(6, length(y.probe))
lims <- c(min(xy[1,])-15, max(xy[1,])+15, min(xy[2,])-15, max(xy[2,]+15))
ex <- f(xy, 200, x.probe, y.probe, lim=lims)
ex$density; ex$integral
#
# Compare the effects of raster resolution and bandwidth.
#
res <- c(8, 40, 200, 1000)
system.time(
est.0 <- sapply(res,
function(i) f(xy, i, x.probe, y.probe, lims=lims)$integral))
est.0
system.time(
est.1 <- sapply(res,
function(i) f(xy, i, x.probe, y.probe, h=1, lims=lims)$integral))
est.1
system.time(
est.2 <- sapply(res,
function(i) f(xy, i, x.probe, y.probe, h=1/2, lims=lims)$integral))
est.2
system.time(
est.3 <- sapply(res,
function(i) f(xy, i, x.probe, y.probe, h=5, lims=lims)$integral))
est.3
results <- data.frame(Default=est.0[,4], Hp5=est.2[,4],
H1=est.1[,4], H5=est.3[,4])
#
# Compare the integrals at the highest resolution.
#
par(mfrow=c(1,1))
panel <- function(x, y, ...) {
points(x, y)
abline(c(0,1), col="Red")
}
pairs(results, lower.panel=panel)
#
# Display two of the density estimates, the data, and the probe points.
#
par(mfrow=c(1,2))
xy.im <- f(xy, 200, x.probe, y.probe, h=0.5)$image
plot(xy.im, main="Bandwidth=1/2", col=terrain.colors(256))
points(t(xy), pch=".", col="Black")
points(x.probe, y.probe, pch=19, col="Red", cex=.5)
xy.im <- f(xy, 200, x.probe, y.probe, h=5)$image
plot(xy.im, main="Bandwidth=5", col=terrain.colors(256))
points(t(xy), pch=".", col="Black")
points(x.probe, y.probe, pch=19, col="Red", cex=.5)