I have a raster layer, which has latitudes and longitudes at a given resolution that determines the total number of grid cells. My goal is to find the distance from each cell to a body of water. How can I go about incorporating bodies of water into the data? Or, should I simply take the raster and add it to something else that already has that data? Is there a source for this? Thanks!
By the way, I did try Googling this, but all of the questions I saw are much more complicated. I've shared code below.
EDIT:
dat<-load('path/data.Rdata')
dat
class : RasterBrick
dimensions : 229, 216, 49464, 52 (nrow, ncol, ncell, nlayers)
resolution : 0.508, 0.24 (x, y)
extent : -149.975, -40.247, 19.92736, 74.88736 (xmin, xmax, ymin,
ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : memory
names : mallar3_p//.1.1.1.1.1, mallar3_p//.2.1.1.1.1,
mallar3_p//.1.2.1.1.1, mallar3_p//.2.2.1.1.1, mallar3_p//.1.1.2.1.1,
mallar3_p//.2.1.2.1.1, mallar3_p//.1.2.2.1.1, mallar3_p//.2.2.2.1.1,
mallar3_p//.1.1.1.2.1, mallar3_p//.2.1.1.2.1, mallar3_p//.1.2.1.2.1,
mallar3_p//.2.2.1.2.1, mallar3_p//.1.1.2.2.1, mallar3_p//.2.1.2.2.1,
mallar3_p//.1.2.2.2.1, ...
min values : 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, ...
max values : 0.0007933783, 0.0010485946,
0.0006397116, 0.0006564575, 0.0006783239,
0.0007855534, 0.0008396646, 0.0007511564,
0.0005148308, 0.0006255456, 0.0006670767,
0.0006578597, 0.0006157646, 0.0003092461,
0.0005634251, ...
Given your RasterBrick has 52 layers, and your intended analysis is not clear, here is a generalisable approach that will create a raster object containing distance in metres to the nearest water body. Methodologically speaking, it makes sense in your case to have a separate raster with distance values which you can then use as the basis of your analysis.
This reprex uses lakes data from the rnaturalearth
package. rnaturalearth
also has river data etc. You can make a composite sf with any number of source data if you need.
As the CRS of your RasterBrick is WGS84/EPSG:4326, you need to ensure your other data have the same CRS. In this case, WGS84/EPSG:4326 is the default CRS for rnaturalearth
data.
The cells in the distance to water body RasterLayer created by the following code align with your original RasterBrick object. This may or may not be the best approach for your analysis, but it does keep things simple. Also, as the closest water body to a given cell may be outside the extent of your RasterBrick, the extend()
function is used to pad the water body RasterLayer by n number of cells (10 in this case). You can increase the extend()
values if necessary.
One further point is that raster()
and sp()
have been deprecated, so to future-proof your work, I encourage you to migrate to the terra
package.
library(rnaturalearth)
library(sf)
library(dplyr)
library(raster)
library(ggplot2)
# Download North America lakes and simplify
lakes_na <- ne_download(scale = 10,
type = "lakes_north_america",
category = "physical") |>
dplyr::select() |>
st_combine() |>
st_as_sf()
# Define the metadata variables from your example
nrow <- 229
ncol <- 216
nlayers <- 52
xmin <- -149.975
xmax <- -40.247
ymin <- 19.92736
ymax <- 74.88736
# Create a template for a water bodies RasterLayer based on your metadata
r <- raster(nrow = nrow, ncol = ncol,
xmn = xmin, xmx = xmax, ymn = ymin, ymx = ymax,
crs = "+proj=longlat +datum=WGS84 +no_defs")
# Extend template RasterLayer to account for water bodies near extent of your data
r <- extend(r, c(10, 10))
# Rasterize water bodies (lakes_na)
rw <- raster::rasterize(lakes_na, r, field = 1, background = NA)
# Calculate distance to the nearest water body
d2w <- distance(rw)
# Convert to df (for illustrative purposes)
d2w_df <- as.data.frame(d2w, xy = TRUE)
# Create polygon sf of extent of your RasterBrick (for illustrative purposes)
sf_poly <- st_as_sfc(st_bbox(c(xmin = xmin,
ymin = ymin,
xmax = xmax,
ymax = ymax))) |>
st_as_sf(crs = 4326)
ggplot() +
geom_tile(data = d2w_df,
aes(x = x, y = y, fill = layer)) +
geom_sf(data = sf_poly,
aes(colour = "RasterBrick extent"),
fill = NA,
linewidth = 1) +
scale_fill_continuous(name = "Distance to water (m)") +
scale_colour_discrete(name = "")
Note that d2w extends beyond the extent of your RasterBrick: