[Solved] How to find distance to nearest habitat and size of nearest habitat patch for a raster in R?

albondiga Asks: How to find distance to nearest habitat and size of nearest habitat patch for a raster in R?
I need to create a raster in R that has three values for each cell. The first value is the habitat type code based on NLCD data. The second value is the distance from each cell to the nearest “natural” habitat patch i.e. distance to the nearest cell with the natural habitat code. The third value is the size of the nearest natural habitat patch.

So for the raster pictured below I have two habitat types “natural” (green) and “nonnatural” (gray). For each nonnatural cell I want to calculate the distance to nearest natural cell as well as the size of the cluster of those natural cells.

I looked through the functions in the package landscapemetrics but it only has options for calculating distance to nearest patch of the same type. Does anyone have any ideas?


An example of a raster with natural and non-natural habitat produced using NLCD data.

Edit:

I’ve created a raster layer that contains, in each cell, the distance to the nearest habitat patch. Here’s the code:

Code:
# create raster
set.seed(1)
r = raster(matrix(runif(100) > .75, 10, 10)

# replace "nonnatural habitat" cells (i.e. cells with values equal to 0) with NA
values(r)[values(r) < 1] = NA

# calculate the distance from each NA cell to the nearest natural habitat cell
distances <- distance(r)

Now I’m working on getting the area of the nearest natural habitat patch for each cell. Using a suggestion by Spacedman I first determined the area of each patch, assigning those values to the cells within the patch:

Code:
set.seed(1)
r = raster(matrix(runif(100)>.75,10,10))

# establish patches
patches <- get_patches(landscape = r, class = 1, directions = 8, return_raster =TRUE) # returns a list that includes a raster with patch id assigned by `get_patches`

# get area of each patch
patchArea <- lsm_p_area(landscape = r, directions = 8)

# store patch id and area as data frame to be merged with the raster
patchAreaDF <- as.data.frame(subset(patchArea, select = c("id", "value")))

# merge raster and patch area data
patchesRaster <- patches$layer_1$class_1
patchesFactor <- as.factor(patchesRaster)
ids <- levels(patchesFactor)[[1]]
colnames(patchAreaDF)[colnames(patchAreaDF) == "id"] <- "ID"
attributes <- merge(ids, patchAreaDF, by = "ID")
levels(patchesFactor) <- attributes
patchesRaster <- deratify(patchesFactor)

Finally, I need to assign the NA cells (those that aren’t part of a patch) with the value of the nearest non-NA cell. This post got me really close but I’m running into a problem. When I run the following code I end up with -Inf values for some of the cells.

Code:
a <- patchesRaster
w <- matrix(1,33)
while (sum(is.na(a[])) > 0) {
a <- focal(a, w, max, na.rm=TRUE, NAonly=TRUE, pad=TRUE)
 return(a)
}

The raster with patch area assigned to cells in each patch.


The raster with patch area assigned to cells in each patch.

The raster after running the while loop. -Inf values in white.


The raster after running the while loop. -Inf values in white.

I’m not sure why the function wouldn’t assign the max area value for the 3×3 window around these cells like it did for other cells on the edge of the raster or within the raster.

I’m also wondering if this method is going to be too computationally intensive when scaled up to a raster with 200,000 cells.

Ten-tools.com may not be responsible for the answers or solutions given to any question asked by the users. All Answers or responses are user generated answers and we do not have proof of its validity or correctness. Please vote for the answer that helped you in order to help others find out which is the most helpful answer. Questions labeled as solved may be solved or may not be solved depending on the type of question and the date posted for some posts may be scheduled to be deleted periodically. Do not hesitate to share your response here to help other visitors like you. Thank you, ten-tools.

 

_


(adsbygoogle = window.adsbygoogle || []).push({});