Menghitung kepadatan jalan di R menggunakan kepadatan kernel? [Tutup]


13

Saya memiliki shapefile jalan yang besar (~ 70MB) dan ingin mengubahnya menjadi raster dengan kepadatan jalan di setiap sel. Idealnya saya ingin melakukan ini di R bersama dengan alat baris perintah GDAL jika perlu.

Pendekatan awal saya adalah secara langsung menghitung panjang segmen garis di setiap sel sesuai utas ini . Ini menghasilkan hasil yang diinginkan, tetapi cukup lambat bahkan untuk shapefile jauh lebih kecil dari milik saya. Berikut adalah contoh yang sangat sederhana yang nilai selnya benar jelas:

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

Imgur

Terlihat bagus, tapi tidak bisa diukur! Dalam beberapa pertanyaan lain, spatstat::density.psp()fungsi tersebut telah direkomendasikan untuk tugas ini. Fungsi ini menggunakan pendekatan kepadatan kernel. Saya dapat mengimplementasikannya dan sepertinya lebih cepat daripada pendekatan di atas, tetapi saya tidak jelas bagaimana memilih parameter atau menginterpretasikan hasilnya. Inilah contoh di atas menggunakan 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

Saya pikir ini mungkin karena pendekatan kernel menghitung kepadatan dibandingkan dengan panjang per sel, jadi saya mengkonversi:

# 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

Tetapi, dalam kedua kasus tersebut, apakah pendekatan kernel mendekati menyelaraskan dengan pendekatan yang lebih langsung di atas.

Jadi, pertanyaan saya adalah:

  1. Bagaimana saya bisa mengartikan output dari density.pspfungsi? Apa saja unitnya?
  2. Bagaimana saya bisa memilih sigmaparameter density.pspsehingga hasilnya sejalan dengan pendekatan yang lebih langsung dan intuitif di atas?
  3. Bonus: apa yang sebenarnya dilakukan kepadatan garis kernel? Saya memiliki beberapa pengertian tentang bagaimana pendekatan ini bekerja untuk poin, tetapi tidak melihat bagaimana itu meluas ke garis.

Jawaban:


8

Saya memposting pertanyaan ini pada listserv R-sig-Geo dan menerima jawaban yang membantu dari Adrian Baddeley, salah satu penulis spatstats . Saya akan memposting interpretasi saya tentang tanggapannya di sini untuk anak cucu.

Adrian mencatat bahwa fungsinya spatstat::pixellate.psp()lebih cocok dengan tugas saya. Fungsi ini mengubah pola segmen garis (atau SpatialLinesobjek dengan konversi) ke gambar piksel (atau RasterLayerdengan konversi), di mana nilai di setiap sel adalah panjang segmen garis yang melewati sel itu. Persis apa yang saya cari!

Resolusi gambar yang dihasilkan dapat didefinisikan dengan epsparameter atau dimyxparameter, yang menetapkan dimensi (jumlah baris dan kolom).

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

Hasilnya persis seperti yang diinginkan.

Adrian juga menjawab pertanyaan saya tentang spatstat::density.psp(). Dia menjelaskan bahwa fungsi ini:

menghitung konvolusi kernel Gaussian dengan garis. Secara intuitif, ini berarti density.psp'mengolesi' garis-garis ke dalam ruang dua dimensi. Jadi density(L)seperti versi kabur dari pixellate(L). Bahkan density(L)sangat mirip dengan di blur(pixellate(L))mana blurada spatstatfungsi lain yang mengaburkan gambar. [Parameter] sigmaadalah bandwidth dari kernel Gaussian. Nilai density.psp(L)pada piksel u yang diberikan, adalah sesuatu seperti jumlah total panjang garis dalam lingkaran sigma jari-jari di sekitar piksel u, kecuali bahwa itu benar-benar merupakan bobot rata-rata dari kontribusi tersebut dari jari-jari lingkaran yang berbeda. Satuan adalah panjang ^ (- 1), yaitu panjang garis per satuan luas.

Masih agak tidak jelas bagi saya ketika pendekatan kernel Gaussian density.psp()akan lebih disukai daripada pendekatan yang lebih intuitif menghitung panjang garis secara langsung di pixellate(). Saya kira saya harus meninggalkan itu untuk para ahli.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.