Tính mật độ đường trong R bằng mật độ hạt nhân? [đóng cửa]


13

Tôi có một hình dạng đường lớn (~ 70 MB) và muốn chuyển đổi nó thành một raster với mật độ đường trong mỗi ô. Lý tưởng nhất là tôi muốn làm điều này trong R cùng với các công cụ dòng lệnh GDAL nếu cần thiết.

Cách tiếp cận ban đầu của tôi là tính trực tiếp độ dài của các đoạn đường trong mỗi ô theo luồng này . Điều này tạo ra kết quả mong muốn, nhưng khá chậm ngay cả đối với các shapefile nhỏ hơn nhiều so với của tôi. Đây là một ví dụ rất đơn giản mà các giá trị ô chính xác là rõ ràng:

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

Có vẻ tốt, nhưng không thể mở rộng! Trong một vài câu hỏi khác, spatstat::density.psp()chức năng đã được đề xuất cho nhiệm vụ này. Hàm này sử dụng cách tiếp cận mật độ nhân. Tôi có thể thực hiện nó và nó có vẻ nhanh hơn cách tiếp cận ở trên, nhưng tôi không rõ làm thế nào để chọn các tham số hoặc giải thích kết quả. Dưới đây là ví dụ trên sử dụng 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

Tôi nghĩ rằng đó có thể là trường hợp phương pháp nhân tính toán mật độ trái ngược với chiều dài trên mỗi ô, vì vậy tôi đã chuyển đổi:

# 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

Nhưng, trong cả hai trường hợp, cách tiếp cận kernel có gần với việc liên kết với cách tiếp cận trực tiếp hơn ở trên không.

Vì vậy, câu hỏi của tôi là:

  1. Làm thế nào tôi có thể giải thích đầu ra của density.pspchức năng? Các đơn vị là gì?
  2. Làm cách nào tôi có thể chọn sigmatham số density.pspđể kết quả phù hợp với cách tiếp cận trực tiếp, trực quan hơn ở trên?
  3. Tiền thưởng: mật độ dòng nhân thực sự đang làm gì? Tôi có một số ý nghĩa về cách các phương pháp này hoạt động cho các điểm, nhưng không thấy cách nó mở rộng ra các dòng.

Câu trả lời:


8

Tôi đã đăng câu hỏi này lên danh sách R-sig-Geo và nhận được câu trả lời hữu ích từ Adrian Baddeley, một trong những tác giả spatstats . Tôi sẽ đăng lời giải thích của tôi về phản ứng của anh ấy ở đây cho hậu thế.

Adrian lưu ý rằng chức năng spatstat::pixellate.psp()này phù hợp hơn với nhiệm vụ của tôi. Hàm này chuyển đổi một mẫu phân đoạn dòng (hoặc SpatialLinesđối tượng có chuyển đổi) thành hình ảnh pixel (hoặc RasterLayervới chuyển đổi), trong đó giá trị trong mỗi ô là độ dài của các phân đoạn dòng đi qua ô đó. Chính xác những gì tôi đang tìm kiếm!

Độ phân giải của hình ảnh kết quả có thể được xác định bằng epstham số hoặc dimyxtham số, đặt kích thước (số lượng hàng và cột).

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

Kết quả chính xác như mong muốn.

Adrian cũng trả lời câu hỏi của tôi về spatstat::density.psp(). Ông giải thích rằng chức năng này:

tính toán tích chập của hạt nhân Gaussian với các dòng. Theo trực giác, điều này có nghĩa là density.psp'bôi nhọ' các đường thẳng vào không gian hai chiều. Vì vậy, density(L)giống như một phiên bản mờ của pixellate(L). Trong thực tế density(L)rất giống với blur(pixellate(L))nơi blurlà một spatstatchức năng làm mờ một hình ảnh. [Tham số] sigmalà băng thông của hạt nhân Gaussian. Giá trị của density.psp(L)một pixel u đã cho, tương đương với tổng độ dài đường trong một vòng tròn bán kính sigma quanh pixel u, ngoại trừ việc nó thực sự là trung bình có trọng số của những đóng góp như vậy từ các bán kính vòng tròn khác nhau. Đơn vị có độ dài ^ (- 1), tức là độ dài dòng trên một đơn vị diện tích.

Tôi vẫn chưa rõ ràng khi phương pháp nhân Gaussian density.psp()được ưa thích hơn phương pháp trực quan hơn về tính toán độ dài đường thẳng trực tiếp pixellate(). Tôi đoán tôi sẽ phải để lại cho các chuyên gia.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.