Обчислення щільності дороги в R за допомогою щільності ядра? [зачинено]


13

У мене є великий (~ 70 Мб) файл форм доріг і хочу перетворити це на растр із щільністю дороги в кожній комірці. В ідеалі я хотів би зробити це в R разом з інструментами командного рядка GDAL, якщо це необхідно.

Мій початковий підхід полягав у тому, щоб безпосередньо обчислити довжини відрізків рядків у кожній комірці відповідно до цієї нитки . Це дає бажані результати, але є досить повільним навіть для форм-файлів, значно менших за мої. Ось дуже спрощений приклад, для якого правильні значення комірок очевидні:

require(sp)
require(raster)
require(rgeos)
require(RColorBrewer)

# Create some sample lines
l1 <- Lines(Line(cbind(c(0,1),c(.25,0.25))), ID="a")
l2 <- Lines(Line(cbind(c(0.25,0.25),c(0,1))), ID="b")
sl <- SpatialLines(list(l1,l2))

# Function to calculate lengths of lines in given raster cell
lengthInCell <- function(i, r, l) {
    r[i] <- 1
    rpoly <- rasterToPolygons(r, na.rm=T)
    lc <- crop(l, rpoly)
    if (!is.null(lc)) {
        return(gLength(lc))
    } else {
        return(0)
    }
}

# Make template
rLength <- raster(extent(sl), res=0.5)

# Calculate lengths
lengths <- sapply(1:ncell(rLength), lengthInCell, rLength, sl)
rLength[] <- lengths

# Plot results
spplot(rLength, scales = list(draw=TRUE), xlab="x", ylab="y", 
       col.regions=colorRampPalette(brewer.pal(9, "YlOrRd")), 
       sp.layout=list("sp.lines", sl), 
       par.settings=list(fontsize=list(text=15)))
round(as.matrix(rLength),3)

#### Results
     [,1] [,2]
[1,]  0.5  0.0
[2,]  1.0  0.5

Імгур

Виглядає добре, але не масштабується! У кількох інших питаннях spatstat::density.psp()функція була рекомендована для цього завдання. Ця функція використовує підхід до щільності ядра. Я в змозі це реалізувати, і це здається швидше, ніж вищевказаний підхід, але мені незрозуміло, як вибрати параметри або інтерпретувати результати. Ось наведений вище приклад із використанням density.psp():

require(spatstat)
require(maptools)

# Convert SpatialLines to psp object using maptools library
pspSl <- as.psp(sl)
# Kernel density, sigma chosen more or less arbitrarily
d <- density(pspSl, sigma=0.01, eps=0.5)
# Convert to raster
rKernDensity <- raster(d)
# Values:
round(as.matrix(rKernDensity),3)

#### Results
      [,1] [,2]
[1,] 0.100  0.0
[2,] 0.201  0.1

Я думав, що це може бути так, що підхід ядра обчислює щільність на відміну від довжини на клітинку, тому я перетворив:

# Convert from density to length per cell for comparison
rKernLength <- rKernDensity * res(rKernDensity)[1] * res(rKernDensity)[2]
round(as.matrix(rKernLength),3)

#### Results
      [,1]  [,2]
[1,] 0.025 0.000
[2,] 0.050 0.025

Але, в жодному випадку, чи підхід ядра не наближається до вирівнювання з більш прямим підходом вище.

Отже, мої запитання:

  1. Як я можу інтерпретувати вихід density.pspфункції? Що таке одиниці?
  2. Як я можу вибрати sigmaпараметр, density.pspщоб результати узгоджувались з більш прямим, інтуїтивним підходом вище?
  3. Бонус: чим насправді займається щільність лінії ядра? Я маю певне розуміння того, як ці підходи працюють для балів, але не бачу, як це поширюється на рядки.

Відповіді:


8

Я розмістив це запитання на R-sig-Geo listserv і отримав корисну відповідь від Адріана Бадделі, одного з авторів шпат-статів . Я опублікую тут своє тлумачення його відповіді для нащадків.

Адріан зазначає, що функція spatstat::pixellate.psp()краще відповідає моєму завданню. Ця функція перетворює шаблон сегмента лінії (або SpatialLinesоб'єкта з перетворенням) в піксельне зображення (або RasterLayerз перетворенням), де значенням у кожній комірці є довжина сегментних рядків, що проходять через цю комірку. Саме те, що я шукаю!

Дозвіл отриманого зображення можна визначити за допомогою epsпараметра або dimyxпараметра, який задає розміри (кількість рядків і стовпців).

require(sp)
require(raster)
require(maptools)
require(spatstat)

# Create some sample lines
l1 <- Lines(Line(cbind(c(0,1),c(.25,0.25))), ID="a")
l2 <- Lines(Line(cbind(c(0.25,0.25),c(0,1))), ID="b")
sl <- SpatialLines(list(l1,l2))

# Convert SpatialLines to psp object using maptools library
pspSl <- as.psp(sl)
# Pixellate with resolution of 0.5, i.e. 2x2 pixels
px <- pixellate(pspSl, eps=0.5)
# This can be converted to raster as desired
rLength <- raster(px)
# Values:
round(as.matrix(rLength),3)

     [,1] [,2]
[1,]  0.5  0.0
[2,]  1.0  0.5

Результати точно такі, як бажано.

Адріан також відповів на мої запитання щодо spatstat::density.psp(). Він пояснює, що ця функція:

обчислює згортку ядра Гаусса з лініями. Інтуїтивно це означає, що density.psp"розмиває" лінії в двовимірний простір. Так density(L)це, як розмита версія pixellate(L). Насправді density(L)дуже схоже на те, blur(pixellate(L))де blurє ще одна spatstatфункція, яка розмиває зображення. [Параметр] sigma- пропускна здатність ядра Гаусса. Значення для density.psp(L)заданого пікселя u є чимось на зразок загальної величини довжини рядка в колі радіусної сигми навколо пікселя u, за винятком того, що це дійсно зважене середнє значення таких внесків з різних радіусів кола. Одиниці довжини ^ (- 1), тобто довжина рядка на одиницю площі.

Мені залишається дещо незрозумілим, коли підхід Гауссового ядра density.psp()буде кращим перед більш інтуїтивним підходом прямого обчислення довжини рядків у pixellate(). Я думаю, що мені доведеться залишити це для експертів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.