Questa è una domanda difficile in quanto non sono state sviluppate molte, se nessuna, statistiche sui processi spaziali sviluppate per le funzionalità di linea. Senza scavare seriamente in equazioni e codice, le statistiche dei processi puntuali non sono prontamente applicabili alle caratteristiche lineari e quindi statisticamente non valide. Questo perché il null, su cui viene testato un determinato modello, si basa su eventi puntuali e non su dipendenze lineari nel campo casuale. Devo dire che non so nemmeno quale sarebbe il nulla per quanto riguarda intensità e disposizione / orientamento sarebbe ancora più difficile.
Qui sto solo sputando, ma mi chiedo se una valutazione su più scale della densità della linea unita alla distanza euclidea (o alla distanza di Hausdorff se le linee sono complesse) non indicherebbe una misura continua di raggruppamento. Questi dati potrebbero quindi essere riassunti ai vettori di linea, usando la varianza per tenere conto della disparità nelle lunghezze (Thomas 2011) e assegnando un valore di cluster usando una statistica come K-medie. So che non stai cercando cluster assegnati, ma il valore del cluster potrebbe suddividere i gradi di clustering. Ciò richiederebbe ovviamente un adattamento ottimale di k, pertanto non vengono assegnati cluster arbitrari. Sto pensando che questo sarebbe un approccio interessante nella valutazione della struttura dei bordi in modelli teorici grafici.
Ecco un esempio funzionante in R, scusate, ma è più veloce e più riproducibile rispetto a fornire un esempio QGIS, ed è più nella mia zona di comfort :)
Aggiungi librerie e usa l'oggetto psp di rame di spatstat come esempio di linea
library(spatstat)
library(raster)
library(spatialEco)
data(copper)
l <- copper$Lines
l <- rotate.psp(l, pi/2)
Calcola la densità di linea standardizzata del 1 ° e 2 ° ordine, quindi passa a oggetti di classe raster
d1st <- density(l)
d1st <- d1st / max(d1st)
d1st <- raster(d1st)
d2nd <- density(l, sigma = 2)
d2nd <- d2nd / max(d2nd)
d2nd <- raster(d2nd)
Standardizzare la densità del 1 ° e 2 ° ordine in una densità integrata nella scala
d <- d1st + d2nd
d <- d / cellStats(d, stat='max')
Calcola la distanza euclidea standardizzata invertita e passa alla classe raster
euclidean <- distmap(l)
euclidean <- euclidean / max(euclidean)
euclidean <- raster.invert(raster(euclidean))
Costruisci spatstat psp su un oggetto SpatialLinesDataFrame da usare in 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)) )
Traccia i risultati
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)
Estrai i valori raster e calcola le statistiche di riepilogo associate a ciascuna riga
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)))
Utilizzare i valori di silhouette del cluster per valutare il k ottimale (numero di cluster), con la funzione optimum.k, quindi assegnare i valori del cluster alle linee. Possiamo quindi assegnare i colori a ciascun cluster e tracciare sopra il raster di densità.
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)
A questo punto si potrebbe eseguire una randomizzazione delle linee per verificare se l'intensità e la distanza risultanti sono significative da casuali. È possibile utilizzare la funzione "rshift.psp" per riorientare casualmente le linee. Puoi anche semplicemente randomizzare i punti di inizio e di fine e ricreare ogni riga.
Ci si chiede anche "what if" se hai appena eseguito un'analisi del modello di punto usando una statistica di analisi univariata o incrociata sui punti di inizio e fine, invariante delle linee. In un'analisi univariata confronteresti i risultati dei punti di inizio e di fine per vedere se c'è coerenza nel raggruppamento tra i due schemi di punti. Questo potrebbe essere fatto tramite un cappello a F, un cappello a G o un cappello a K di Ripley (per processi a punti non contrassegnati). Un altro approccio sarebbe un'analisi incrociata (es., Cross-K) in cui i processi a due punti vengono testati simultaneamente contrassegnandoli come [start, stop]. Ciò indicherebbe le relazioni di distanza nel processo di raggruppamento tra i punti iniziale e finale. Tuttavia, la dipendenza spaziale (nonstaionarity) da un processo di intensità sottostante può essere un problema in questi tipi di modelli rendendoli disomogenei e richiedendo un modello diverso. Ironia della sorte, il processo disomogeneo viene modellato usando una funzione di intensità che ci riporta al cerchio completo alla densità, supportando così l'idea di utilizzare una densità integrata nella scala come misura del clustering.
Ecco un rapido esempio di se la statistica Ripleys K (Besags L) per la correlazione automatica di un processo punto non marcato usando le posizioni di inizio, fine di una classe di feature di linea. L'ultimo modello è un cross-k che utilizza entrambe le posizioni di inizio e fine come processo contrassegnato nominale.
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) ) )
Riferimenti
Thomas JCR (2011) Un nuovo algoritmo di clustering basato su K-medie usando un segmento di linea come prototipo. In: San Martin C., Kim SW. (a cura di) Progressi in Pattern Recognition, Image Analysis, Computer Vision e Applications. CIARP 2011. Appunti di lezione in Informatica, vol 7042. Springer, Berlino, Heidelberg