Это сложный вопрос, так как статистических данных о пространственных процессах, разработанных для линейных объектов, было немного. Без серьезного изучения уравнений и кода статистика точечных процессов не всегда применима к линейным объектам и, следовательно, статистически неверна. Это связано с тем, что значение null, с которым проверяется данный шаблон, основано на точечных событиях, а не на линейных зависимостях в случайном поле. Я должен сказать, что я даже не знаю, каким будет ноль, поскольку интенсивность и расположение / ориентация будет еще сложнее.
Я здесь просто плевок, но мне интересно, не будет ли многомерная оценка плотности линий в сочетании с евклидовым расстоянием (или расстоянием Хаусдорфа, если линии сложные) не будет указывать на непрерывную меру кластеризации. Затем эти данные можно суммировать с векторными линиями, используя дисперсию для учета несоответствия длин (Thomas 2011), и назначить значение кластера с использованием статистики, такой как K-средних. Я знаю, что вы не после назначенных кластеров, но значение кластера может разделить степени кластеризации. Это, очевидно, потребовало бы оптимального соответствия k, поэтому произвольные кластеры не назначаются. Я думаю, что это был бы интересный подход при оценке структуры ребер в теоретических моделях графа.
Вот проработанный пример на R, извините, но он быстрее и более воспроизводим, чем пример QGIS, и больше в моей зоне комфорта :)
Добавьте библиотеки и используйте медный объект psp из spatstat в качестве примера строки
library(spatstat)
library(raster)
library(spatialEco)
data(copper)
l <- copper$Lines
l <- rotate.psp(l, pi/2)
Вычислить стандартизированную плотность линий 1-го и 2-го порядка, а затем привести к объектам класса растра
d1st <- density(l)
d1st <- d1st / max(d1st)
d1st <- raster(d1st)
d2nd <- density(l, sigma = 2)
d2nd <- d2nd / max(d2nd)
d2nd <- raster(d2nd)
Стандартизировать плотность 1-го и 2-го порядка в масштабированную плотность
d <- d1st + d2nd
d <- d / cellStats(d, stat='max')
Рассчитать стандартизированное инвертированное евклидово расстояние и привести к классу растра
euclidean <- distmap(l)
euclidean <- euclidean / max(euclidean)
euclidean <- raster.invert(raster(euclidean))
Принуждение spatstat psp к объекту sp SpatialLinesDataFrame для использования в 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)) )
Результаты участка
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)
Извлечение растровых значений и вычисление сводной статистики, связанной с каждой строкой
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)))
Используйте значения силуэта кластера для оценки оптимального k (количества кластеров) с помощью функции optim.k, а затем присвойте значения кластера строкам. Затем мы можем назначить цвета для каждого кластера и нанести график поверх растра плотности.
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)
В этот момент можно выполнить рандомизацию линий, чтобы проверить, являются ли результирующая интенсивность и расстояние значимыми от случайных. Вы можете использовать функцию rshift.psp, чтобы случайным образом переориентировать ваши строки. Вы также можете просто рандомизировать начальную и конечную точки и воссоздать каждую строку.
Также возникает вопрос: «Что, если» вы только что выполнили точечный анализ с использованием однофакторной или перекрестной статистики анализа начальных и конечных точек, инвариантных линий. В одномерном анализе вы сравниваете результаты начальной и конечной точек, чтобы увидеть, есть ли согласованность в кластеризации между двумя точечными образцами. Это можно сделать с помощью f-hat, G-hat или Ripley's-K-hat (для немаркированных точечных процессов). Другим подходом может быть перекрестный анализ (например, перекрестный К), где два точечных процесса проверяются одновременно, помечая их как [начало, остановка]. Это будет указывать на отношения расстояний в процессе кластеризации между начальной и конечной точками. Тем не мение, пространственная зависимость (нестационарность) от лежащего в основе процесса интенсивности может быть проблемой в моделях такого типа, делая их неоднородными и требующими другой модели. По иронии судьбы, неоднородный процесс моделируется с использованием функции интенсивности, которая возвращает нас к плотности, тем самым поддерживая идею использования интегрированной по масштабу плотности в качестве меры кластеризации.
Вот быстрый пример использования статистики Ripleys K (Besags L) для автокорреляции процесса без опознавательных точек с использованием начальных и конечных положений класса линейных объектов. Последняя модель представляет собой кросс-к, использующий места начала и остановки в качестве номинально отмеченного процесса.
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) ) )
Ссылки
Thomas JCR (2011) Новый алгоритм кластеризации на основе K-средних с использованием линейного сегмента в качестве прототипа. В кн .: Сан Мартин С., Ким С.В. (eds) Прогресс в распознавании образов, анализе изображений, компьютерном зрении и приложениях. CIARP 2011. Конспект лекций в области компьютерных наук, том 7042. Springer, Берлин, Гейдельберг