Це складне питання, оскільки просто не було багато просторових статистичних процесів, розроблених для особливостей ліній. Без серйозного заглиблення в рівняння та код, статистика точкових процесів не легко застосувати до лінійних ознак і, таким чином, статистично недійсна. Це тому, що нуль, на який протестується дана закономірність, ґрунтується на точкових подіях, а не лінійних залежності у випадковому полі. Треба сказати, що я навіть не знаю, якою буде нуль, наскільки інтенсивність та розташування / орієнтація будуть ще складнішими.
Я просто плюнув кулю, але мені цікаво, чи багатомасштабна оцінка щільності лінії в поєднанні з евклідовою відстані (або відстань Хаусдорфа, якщо лінії складні) не вказуватиме на постійний показник кластеризації. Потім ці дані можуть бути узагальнені до лінійних векторів, використовуючи відмінність для обліку розбіжності в довжинах (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)
Обчисліть стандартизовану щільність рядків першого та другого порядку, а потім примусьте до об'єктів растрового класу
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 (кількість кластерів) за допомогою функції optimal.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-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) ) )
Список літератури
Томас JCR (2011) Новий алгоритм кластеризації, заснований на K-засобах, що використовують як прототип лінійний сегмент. В: Сан-Мартин С., Кім SW. (eds) Прогрес у розпізнаванні візерунків, аналізі зображень, комп’ютерному баченні та додатках. CIARP 2011. Конспекти лекцій з інформатики, т. 7042. Спрингер, Берлін, Гейдельберг