To trudne pytanie, ponieważ po prostu nie opracowano wielu, jeśli w ogóle, statystyk procesu przestrzennego dla cech linii. Bez poważnego zagłębiania się w równania i kod, statystyki procesu punktowego nie mają łatwego zastosowania do cech liniowych, a zatem są statystycznie niepoprawne. Jest tak, ponieważ zero, na którym testowany jest dany wzorzec, opiera się na zdarzeniach punktowych, a nie liniowych zależnościach w polu losowym. Muszę powiedzieć, że nawet nie wiem, jaka byłaby wartość zerowa, o ile intensywność i układ / orientacja byłyby jeszcze trudniejsze.
Po prostu tutaj kulę pluć, ale zastanawiam się, czy wieloskalowa ocena gęstości linii w połączeniu z odległością euklidesową (lub odległości Hausdorffa, jeśli linie są złożone) nie wskazywałaby na ciągłą miarę skupiania. Dane te można następnie podsumować do wektorów liniowych, używając wariancji, aby uwzględnić rozbieżności długości (Thomas 2011), i przypisać wartość skupienia za pomocą statystyki, takiej jak K-średnie. Wiem, że nie jesteś po przypisanych klastrach, ale wartość klastra może podzielić stopnie klastrowania. Wymagałoby to oczywiście optymalnego dopasowania k, więc arbitralne klastry nie są przypisywane. Myślę, że byłoby to interesujące podejście do oceny struktury krawędzi w teoretycznych modelach graficznych.
Oto działający przykład w R, przepraszam, ale jest szybszy i bardziej powtarzalny niż dostarczanie przykładu QGIS i jest bardziej w mojej strefie komfortu :)
Dodaj biblioteki i użyj miedzianego obiektu psp ze spatstat jako przykładu linii
library(spatstat)
library(raster)
library(spatialEco)
data(copper)
l <- copper$Lines
l <- rotate.psp(l, pi/2)
Oblicz standaryzowaną gęstość linii pierwszego i drugiego rzędu, a następnie wymusz na obiektach klasy rastrowej
d1st <- density(l)
d1st <- d1st / max(d1st)
d1st <- raster(d1st)
d2nd <- density(l, sigma = 2)
d2nd <- d2nd / max(d2nd)
d2nd <- raster(d2nd)
Standaryzuj gęstość pierwszego i drugiego rzędu do gęstości zintegrowanej ze skalą
d <- d1st + d2nd
d <- d / cellStats(d, stat='max')
Oblicz znormalizowaną odwróconą odległość euklidesową i przymus do klasy rastrowej
euclidean <- distmap(l)
euclidean <- euclidean / max(euclidean)
euclidean <- raster.invert(raster(euclidean))
Wymuś spatstat psp na obiekt SpatialLinesDataFrame do użycia w 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)) )
Wykreśl wyniki
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)
Wyodrębnij wartości rastrowe i oblicz statystyki podsumowujące związane z każdą linią
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)))
Użyj wartości sylwetki klastra, aby ocenić optymalną wartość k (liczbę klastrów), z funkcją optimum.k, a następnie przypisz wartości klastra do linii. Następnie możemy przypisać kolory do każdego skupienia i narysować na górze rastra gęstości.
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)
W tym momencie można przeprowadzić randomizację linii, aby sprawdzić, czy uzyskana intensywność i odległość są znaczące w stosunku do losowości. Możesz użyć funkcji „rshift.psp”, aby losowo zmienić orientację linii. Możesz także po prostu randomizować punkty początkowe i końcowe oraz odtworzyć każdą linię.
Zastanawia się także „co jeśli” właśnie wykonałeś analizę wzoru punktowego za pomocą statystyki analizy jednowymiarowej lub krzyżowej na punktach początkowym i końcowym, niezmiennej dla linii. W analizie jednoczynnikowej porównywałbyś wyniki punktów początkowych i końcowych, aby sprawdzić, czy istnieje spójność w grupowaniu między dwoma wzorcami punktowymi. Można to zrobić za pomocą f-hat, G-hat lub Ripley's-K-hat (dla nieoznaczonych procesów punktowych). Innym podejściem byłaby analiza krzyżowa (np. Cross-K), w której dwa procesy punktowe są testowane jednocześnie poprzez oznaczenie ich jako [start, stop]. Oznaczałoby to relacje odległości w procesie grupowania między punktami początkowym i końcowym. Jednak, zależność przestrzenna (niestacjonarność) od leżącego u podstaw procesu intensywności może stanowić problem w tego typu modelach, czyniąc je niejednorodnymi i wymagającymi innego modelu. Jak na ironię, niejednorodny proces jest modelowany za pomocą funkcji intensywności, która przywraca nam pełne koło z powrotem do gęstości, wspierając w ten sposób ideę wykorzystania gęstości zintegrowanej ze skalą jako miary skupienia.
Oto szybko działający przykład, czy statystyka Ripleys K (Besags L) do autokorelacji procesu nieoznaczonego punktu przy użyciu lokalizacji początkowej i końcowej klasy obiektów liniowych. Ostatni model to cross-k wykorzystujący zarówno lokalizację początkową, jak i końcową jako proces oznaczony nominalnie.
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) ) )
Referencje
Thomas JCR (2011) Nowy algorytm grupowania oparty na środkach K przy użyciu segmentu linii jako prototypu. W: San Martin C., Kim SW. (eds) Postępy w rozpoznawaniu wzorów, analizie obrazu, wizji komputerowej i aplikacjach. CIARP 2011. Uwagi do wykładu z informatyki, tom 7042. Springer, Berlin, Heidelberg