Qual è il modo corretto di calcolare la stima della densità del kernel dalle coordinate geografiche?


11

Devo calcolare la stima della densità del kernel 2d (kde) da un elenco di coordinate di latitudine e longitudine. Ma un grado in latitudine non è la stessa distanza di un grado in longitudine, ciò significa che i singoli kernel sarebbero ovali, specialmente più il punto è dall'equatore.

Nel mio caso i punti sono tutti abbastanza vicini l'uno all'altro che trasformarli in terra piatta non dovrebbe causare molti problemi. Tuttavia sono ancora curioso di sapere come dovrebbe essere gestito correttamente nel caso in cui ciò non fosse vero.


Come prima ipotesi, suppongo che sostituiresti una metrica di distanza sferica appropriata in un approccio kernel standard.
Sycorax dice di reintegrare Monica il

Chi può dire che avere kernel ovali non sia corretto?
gung - Ripristina Monica

1
@gung Immagina cosa succederebbe se posizionassi un punto abbastanza vicino a un palo. Sarebbe schiacciato lungo l'asse longitudinale. E come gestiresti un kernel che copre effettivamente uno dei poli?
Aaron de Windt,

Avresti un nodulo sopra il palo che è ugualmente alto in tutte le longitudini. Perché è sbagliato?
gung - Ripristina Monica

@gung Perché se per esempio scegliessi un diametro del kernel di 1 grado non sarebbe su tutte le longitudini. Sarebbe oltre 1 grado longitudinale che potrebbe essere solo di pochi metri se il punto è abbastanza vicino al polo, rispetto ai ~ 110 km che sono 1 grado latitudinale.
Aaron de Windt,

Risposte:


7

Potresti prendere in considerazione l'uso di un kernel particolarmente adatto alla sfera, come una densità di von Mises-Fisher

f(x;κ,μ)exp(κμx)

dove e sono posizioni sulla sfera unitaria espresse in coordinate cartesiane 3D.μx

L'analogo della larghezza di banda è il parametro . Il contributo a una posizione da un punto di ingresso nella posizione sulla sfera, avente peso , quindi èκxμω(μ)

ω(μ)f(x;κ,μ).

Per ogni , sommare questi contributi su tutti i punti di input .xμi

Per illustrare, ecco il Rcodice per calcolare la densità di von Mises-Fisher, generare alcune posizioni casuali e pesi (12 di esse nel codice) e visualizzare una mappa della densità del kernel risultante per un determinato valore di (uguale a nel codice).μiω(μi)κ6

[Figura]

I punti sono mostrati come punti neri dimensionati per avere aree proporzionali ai loro pesi . Il contributo del punto grande vicino è evidente in tutte le latitudini settentrionali. La brillante macchia giallo-bianca attorno ad essa sarebbe approssimativamente circolare quando mostrata in una proiezione adatta, come un ortografico (terra dallo spazio).μiω(μi)(100,60)

#
# von Mises-Fisher density.
# mu is the location and x the point of evaluation, *each in lon-lat* coordinates.
# Optionally, x is a two-column array.
#
dvonMises <- function(x, mu, kappa, inDegrees=TRUE) {
  lambda <- ifelse(inDegrees, pi/180, 1)
  SphereToCartesian <- function(x) {
    x <- matrix(x, ncol=2)
    t(apply(x, 1, function(y) c(cos(y[2])*c(cos(y[1]), sin(y[1])), sin(y[2]))))
  }
  x <- SphereToCartesian(x * lambda)
  mu <- matrix(SphereToCartesian(mu * lambda), ncol=1)

  c.kappa <- kappa / (2*pi*(exp(kappa) - exp(-kappa)))
  c.kappa * exp(kappa * x %*% mu)
}
#
# Define a grid on which to compute the kernel density estimate.
#
x.coord <- seq(-180, 180, by=2)
y.coord <- seq(-90, 90, by=1)
x <- as.matrix(expand.grid(lon=x.coord, lat=y.coord))
#
# Give the locations.
#
n <- 12
set.seed(17)
mu <- cbind(runif(n, -180, 180), asin(runif(n, -1, 1))*180/pi)
#
# Weight them.
#
weights <- rexp(n)
#
# Compute the kernel density.
#
kappa <- 6
z <- numeric(nrow(x))
for (i in 1:nrow(mu)) {
  z <- z + weights[i] * dvonMises(x, mu[i, ], kappa)
}
z <- matrix(z, nrow=length(x.coord))
#
# Plot the result.
#
image(x.coord, y.coord, z, xlab="Longitude", ylab="Latitude")
points(mu[, 1], mu[, 2], pch=16, cex=sqrt(weights))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.