Esta es una pregunta difícil, ya que no se han desarrollado muchas estadísticas de procesos espaciales, si es que hay alguna, para las características de línea. Sin profundizar en las ecuaciones y el código, las estadísticas de proceso puntual no son fácilmente aplicables a las características lineales y, por lo tanto, estadísticamente inválidas. Esto se debe a que el valor nulo, contra el que se prueba un patrón determinado, se basa en eventos puntuales y no en dependencias lineales en el campo aleatorio. Tengo que decir que ni siquiera sé cuál sería el valor nulo en la medida en que la intensidad y la disposición / orientación serían aún más difíciles.
Aquí solo estoy escupiendo, pero me pregunto si una evaluación a gran escala de la densidad de la línea junto con la distancia euclidiana (o la distancia de Hausdorff si las líneas son complejas) no indicaría una medida continua de agrupamiento. Estos datos podrían resumirse luego en los vectores de línea, utilizando la varianza para tener en cuenta la disparidad en las longitudes (Thomas 2011), y se les asignó un valor de agrupación utilizando una estadística como K-medias. Sé que no buscas los clústeres asignados, pero el valor del clúster podría dividir los grados de clúster. Obviamente, esto requeriría un ajuste óptimo de k, por lo que no se asignan grupos arbitrarios. Estoy pensando que este sería un enfoque interesante para evaluar la estructura de borde en modelos teóricos gráficos.
Aquí hay un ejemplo trabajado en R, lo siento, pero es más rápido y más reproducible que proporcionar un ejemplo de QGIS, y está más en mi zona de confort :)
Agregue bibliotecas y use objetos psp de cobre desde spatstat como ejemplo de línea
library(spatstat)
library(raster)
library(spatialEco)
data(copper)
l <- copper$Lines
l <- rotate.psp(l, pi/2)
Calcule la densidad de línea estandarizada de primer y segundo orden y luego coaccione a objetos de clase ráster
d1st <- density(l)
d1st <- d1st / max(d1st)
d1st <- raster(d1st)
d2nd <- density(l, sigma = 2)
d2nd <- d2nd / max(d2nd)
d2nd <- raster(d2nd)
Estandarice la densidad de primer y segundo orden en una densidad integrada en la escala
d <- d1st + d2nd
d <- d / cellStats(d, stat='max')
Calcule la distancia euclidiana invertida estandarizada y la coerción a la clase de trama
euclidean <- distmap(l)
euclidean <- euclidean / max(euclidean)
euclidean <- raster.invert(raster(euclidean))
Coaccione el psp de spstastat a un objeto sp SpatialLinesDataFrame para usar en raster :: extract
as.SpatialLines.psp <- local({
ends2line <- function(x) Line(matrix(x, ncol=2, byrow=TRUE))
munch <- function(z) { Lines(ends2line(as.numeric(z[1:4])), ID=z[5]) }
convert <- function(x) {
ends <- as.data.frame(x)[,1:4]
ends[,5] <- row.names(ends)
y <- apply(ends, 1, munch)
SpatialLines(y)
}
convert
})
l <- as.SpatialLines.psp(l)
l <- SpatialLinesDataFrame(l, data.frame(ID=1:length(l)) )
Resultados de la trama
par(mfrow=c(2,2))
plot(d1st, main="1st order line density")
plot(l, add=TRUE)
plot(d2nd, main="2nd order line density")
plot(l, add=TRUE)
plot(d, main="integrated line density")
plot(l, add=TRUE)
plot(euclidean, main="euclidean distance")
plot(l, add=TRUE)
Extraiga valores ráster y calcule estadísticas de resumen asociadas con cada línea
l.dist <- extract(euclidean, l)
l.den <- extract(d, l)
l.stats <- data.frame(min.dist = unlist(lapply(l.dist, min)),
med.dist = unlist(lapply(l.dist, median)),
max.dist = unlist(lapply(l.dist, max)),
var.dist = unlist(lapply(l.dist, var)),
min.den = unlist(lapply(l.den, min)),
med.den = unlist(lapply(l.den, median)),
max.den = unlist(lapply(l.den, max)),
var.den = unlist(lapply(l.den, var)))
Use valores de silueta de clúster para evaluar k óptimo (número de clústeres), con la función óptima.k, luego asigne valores de clúster a las líneas. Luego podemos asignar colores a cada grupo y trazar en la parte superior del ráster de densidad.
clust <- optimal.k(scale(l.stats), nk = 10, plot = TRUE)
l@data <- data.frame(l@data, cluster = clust$clustering)
kcol <- ifelse(clust$clustering == 1, "red", "blue")
plot(d)
plot(l, col=kcol, add=TRUE)
En este punto, se podría realizar una aleatorización de las líneas para probar si la intensidad y la distancia resultantes son significativas respecto al azar. Puede usar la función "rshift.psp" para reorientar sus líneas aleatoriamente. También podría aleatorizar los puntos de inicio y finalización y recrear cada línea.
Uno también se pregunta "qué pasaría si" acaba de realizar un análisis de patrón de puntos utilizando una estadística de análisis univariado o cruzado en los puntos de inicio y finalización, invariante de las líneas. En un análisis univariante, compararía los resultados de los puntos de inicio y finalización para ver si existe consistencia en la agrupación entre los dos patrones de puntos. Esto podría hacerse mediante un f-hat, G-hat o Ripley's-K-hat (para procesos de puntos sin marcar). Otro enfoque sería un análisis cruzado (por ejemplo, cross-K) donde los procesos de dos puntos se prueban simultáneamente marcándolos como [inicio, parada]. Esto indicaría las relaciones de distancia en el proceso de agrupación entre los puntos inicial y final. Sin embargo, La dependencia espacial (no estacionaria) de un proceso de intensidad subyacente puede ser un problema en este tipo de modelos, haciéndolos no homogéneos y requiriendo un modelo diferente. Irónicamente, el proceso no homogéneo se modela utilizando una función de intensidad que nos devuelve el círculo completo a la densidad, lo que respalda la idea de utilizar una densidad integrada en la escala como medida de agrupamiento.
Aquí hay un ejemplo rápido y trabajado de si la estadística Ripleys K (Besags L) para la autocorrelación de un proceso de puntos sin marcar utilizando las ubicaciones de inicio y detención de una clase de entidad de línea. El último modelo es un cross-k que usa las ubicaciones de inicio y parada como un proceso marcado nominal.
library(spatstat)
data(copper)
l <- copper$Lines
l <- rotate.psp(l, pi/2)
Lr <- function (...) {
K <- Kest(...)
nama <- colnames(K)
K <- K[, !(nama %in% c("rip", "ls"))]
L <- eval.fv(sqrt(K/pi)-bw)
L <- rebadge.fv(L, substitute(L(r), NULL), "L")
return(L)
}
### Ripley's K ( Besag L(r) ) for start locations
start <- endpoints.psp(l, which="first")
marks(start) <- factor("start")
W <- start$window
area <- area.owin(W)
lambda <- start$n / area
ripley <- min(diff(W$xrange), diff(W$yrange))/4
rlarge <- sqrt(1000/(pi * lambda))
rmax <- min(rlarge, ripley)
( Lenv <- plot( envelope(start, fun="Lr", r=seq(0, rmax, by=1), nsim=199, nrank=5) ) )
### Ripley's K ( Besag L(r) ) for end locations
stop <- endpoints.psp(l, which="second")
marks(stop) <- factor("stop")
W <- stop$window
area <- area.owin(W)
lambda <- stop$n / area
ripley <- min(diff(W$xrange), diff(W$yrange))/4
rlarge <- sqrt(1000/(pi * lambda))
rmax <- min(rlarge, ripley)
( Lenv <- plot( envelope(start, fun="Lr", r=seq(0, rmax, by=1), nsim=199, nrank=5) ) )
### Ripley's Cross-K ( Besag L(r) ) for start/stop
sdata.ppp <- superimpose(start, stop)
( Lenv <- plot(envelope(sdata.ppp, fun="Kcross", r=bw, i="start", j="stop", nsim=199,nrank=5,
transform=expression(sqrt(./pi)-bw), global=TRUE) ) )
Referencias
Thomas JCR (2011) Un nuevo algoritmo de agrupamiento basado en K-medias utilizando un segmento de línea como prototipo. En: San Martin C., Kim SW. (eds) Progreso en reconocimiento de patrones, análisis de imágenes, visión por computadora y aplicaciones. CIARP 2011. Lecture Notes in Computer Science, vol 7042. Springer, Berlín, Heidelberg