我很难通过
create_lcp
包中的命令 leastcostpath
获得正确的最低成本路径。该问题已记录在最小工作示例中。
特别是,当我避免通过
gdistance
和相关的 geoCorrection
命令创建过渡层,而是使用 create_cs
包中的 leastcostpath
命令时,就会出现问题。这会从一些初始成本栅格开始生成一个 conductanceMatrix
对象。如示例中所述,create_cs
命令更改栅格中包含的成本结构,这是第一个问题。但即使根据这种改变的成本结构,由此产生的最低成本路径也无法最小化成本。
我做错了什么?
library(sf)
library(terra)
library(leastcostpath)
# Create toy cost raster with projected coordinates
nr <- 5
nc <- 3
m <- matrix(
data = c(1,NA,NA,
1,1,NA,
2,3,1,
1,1,1,
NA,1,NA),
nrow = nr,
ncol = nc,
byrow = T)
cost.r <- rast(m,crs = "EPSG:3003")
plot(cost.r)
# Create conductance matrix via <create_cs>
conductanceMatrix <- create_cs(
x = cost.r,
neighbours = 8)
plot(conductanceMatrix)
# Obtain polygons from cells
pgn.inn <- as.polygons(cost.r,
aggregate = F,
na.rm = T,
na.all = T)
pgn.inn <- st_as_sf(pgn.inn)
# Cell centroids
ctr.inn <- st_centroid(pgn.inn)
# Pick two endpoints
endpts <- ctr.inn[c(1,4) ,1]
# LCP
lcp <- create_lcp(conductanceMatrix,
endpts[1,],
endpts[2,],
cost_distance = T)
# Plot
pal <- c("lightgreen","orange","red")
plot(
# main = paste("Combination",i),
conductanceMatrix,
col = pal,
colNA = NA,
axes = F,
box = F,
legend = T
)
plot(st_as_sfc(pgn.inn), border = "white", lwd = 0.2, add = T)
plot(
st_as_sfc(lcp),
col = "black",
lwd = 2,
axes = F,
add = T
)
plot(
st_as_sfc(endpts),
pch = 16,
cex = 1,
col = "black",
axes = F,
add = T
)
我详细阅读了
leastcostpath
包的手册,也查看了其create_cs
函数的代码,但我不明白是什么原因导致了上述问题。
首先,感谢您使用 R 包leastcostpath!
如果您有成本面,则需要在将其提供给 create_cs() 之前将其反转。此功能以及更一般的封装使用电导值来工作,即值越高,导电性越好/成本越低。
m <- 1/m
就 create_cs 更改提供的栅格而言,只有在绘制电导矩阵(或使用leastcostpath::rasterise)时才会出现这种情况。我试图在下面解释它是如何工作的。希望这会有所帮助。
使用你的玩具示例
library(sf)
library(terra)
library(leastcostpath)
# Create toy cost raster with projected coordinates
nr <- 5
nc <- 3
m <- matrix(
data = c(1,NA,NA,
1,1,NA,
2,3,1,
1,1,1,
NA,1,NA),
nrow = nr,
ncol = nc,
byrow = T)
cost.r <- rast(m,crs = "EPSG:3003")
plot(cost.r)
#plotted the values in the spatRaster so we can visualise
text(cost.r)
# Create conductance matrix via <create_cs>
conductanceMatrix <- create_cs(
x = cost.r,
neighbours = 8)
# the plot() function for a conductanceMatrix mean averages all values going into/out of that cell
# for example, given the neighbourhood of 8 there are 7 cells connected to cell 8 (the central cell with a value of 3). In total, the total conductivity to that central cell is 21 (3*7)
# The central cell is also connected to 7 cells. This time the total conductivity is 8 (1+1+2+1+1+1+1)
# so the average conductance value to the central cell is 3 (21/7, because the total conductance is 21 and there are 7 cels)
# the average conductance from the central cell is 1.142857 (8/7)
# so the average overall is 2.071429 ((3 + 1.142857)/2)
# this is what you see when you plot the conductance matrix
plot(conductanceMatrix)
text(rasterise(conductanceMatrix))
# the actual values are not changed. For example, below shows us conductance to the central cell. We can see that the conductance to that cell is 3 (given that this cell has a conductance of 3 from the supplied spatRaster). Also, the non-zeros show us which cells are connected to the central cell. for example, the first 3 refers to cell 4, (i.e. the cell top-left from the central cell), 4th refers to cell 5 (above central cell, etc)
conductanceMatrix$conductanceMatrix[,8]
# Obtain polygons from cells
pgn.inn <- as.polygons(cost.r,
aggregate = F,
na.rm = T,
na.all = T)
pgn.inn <- st_as_sf(pgn.inn)
# Cell centroids
ctr.inn <- st_centroid(pgn.inn)
# Pick two endpoints
endpts <- ctr.inn[c(1,4) ,1]
# LCP
lcp <- create_lcp(conductanceMatrix,
endpts[1,],
endpts[2,],
cost_distance = T)
# Plot
pal <- c("lightgreen","orange","red")
plot(
# main = paste("Combination",i),
conductanceMatrix,
col = pal,
colNA = NA,
axes = F,
box = F,
legend = T
)
plot(st_as_sfc(pgn.inn), border = "white", lwd = 0.2, add = T)
plot(
st_as_sfc(lcp),
col = "black",
lwd = 2,
axes = F,
add = T
)
plot(
st_as_sfc(endpts),
pch = 16,
cex = 1,
col = "black",
axes = F,
add = T
)
请注意,在玩具示例中,最终的 LCP(先向东南然后向西南)的成本与 LCP 直接向南到达目的地位置的成本相同。因此,这两条路线在技术上都是成本最低的路径。我需要看看 igraph Shortest.path 如何决定返回哪一个(还要检查我是否已经做到了,以便在 create_lcp() 函数中只返回一个。