I'm using this function to calculate the length of linestring per cell by ID and store in a list, convert each element of the list into a RasterLayer and turn that list into a RasterBrick. Notice that inside the function I use "left_join()" so that all rasters have the same number of cells. However, the final raster converts to RasterStack instead of RasterBrick, why does this happen?
library(tidyverse)
library(sf)
library(raster)
library(purrr)
id <- c("844", "844", "844", "844", "844","844", "844", "844", "844", "844",
"844", "844", "845", "845", "845", "845", "845","845", "845", "845",
"845","845", "845", "845")
lat <- c(-30.6456, -29.5648, -27.6667, -31.5587, -30.6934, -29.3147, -23.0538,
-26.5877, -26.6923, -23.40865, -23.1143, -23.28331, -31.6456, -24.5648,
-27.6867, -31.4587, -30.6784, -28.3447, -23.0466, -27.5877, -26.8524,
-23.8855, -24.1143, -23.5874)
long <- c(-50.4879, -49.8715, -51.8716, -50.4456, -50.9842, -51.9787, -41.2343,
-40.2859, -40.19599, -41.64302, -41.58042, -41.55057, -50.4576, -48.8715,
-51.4566, -51.4456, -50.4477, -50.9937, -41.4789, -41.3859, -40.2536,
-41.6502, -40.5442, -41.4057)
df <- tibble(id, lat, long)
#converting to sf
df.sf <- df %>%
sf::st_as_sf(coords = c("long", "lat"), crs = 4326)
I also have a sf grid created from points:
#creating grid
xy <- sf::st_coordinates(df.sf)
grid = sf::st_make_grid(sf::st_bbox(df.sf),
cellsize = .1, square = FALSE) %>%
sf::st_as_sf() %>%
dplyr::mutate(cell = 1:nrow(.))
#creating raster
r <- raster::raster(grid, res=0.1)
#creating linestring to each id
df.line <- df.sf %>%
dplyr::group_by(id) %>%
dplyr::summarize() %>%
sf::st_cast("LINESTRING")
#build_length_raster <- function(df.line) {
intersect_list <- by(
df.line,
df.line$id,
function(id_df) sf::st_intersection(grid, id_df) %>%
dplyr::mutate(length = as.numeric(sf::st_length(.))) %>%
sf::st_drop_geometry()
)
list_length_grid <- purrr::map(intersect_list, function(grid_id) {
grid_id %>% dplyr::left_join(x=grid, by="cell") %>%
dplyr::mutate(length=length) %>%
dplyr::mutate_if(is.numeric,coalesce,0)
})
list_length_raster <- purrr::map(list_length_grid, function(grid_id) {
raster::rasterize(grid_id, r, field="length", na.rm=F, background=0)
})
list_length_raster2 <- unlist(list_length_raster, recursive=F)
raster_brick <- raster::writeRaster(raster::brick(list_length_raster2 ),
names(list_length_raster2 ),
bylayer=TRUE, overwrite=TRUE)
#}
You use the argument
bylayer=TRUE
asking for a separate file for each layer. A RasterBrick can only be created from a single file; hence you get a RasterStack.Also, because you have a list of RasterLayers, it is more efficient to use
stack
here instead ofbrick
.This is because a RasterStack essentially is a list or RasterLayers. With brick you would combine all the values into a new structure, and that can be expensive.
And if you want a RasterBrick, do:
Or use
terra
instead ofraster
--- That is easier because theterra
SpatRaster
encompassesraster
's RasterLayer, Stack and Brick objects.Below I show how you may do this with
terra
(although I am not quite following all the logic of your script; my understanding is that you want to measure, for each grid cell, the length of the lines that cross it). You need terra >= 1.5-29 that you can install withinstall.packages('terra', repos='https://rspatial.r-universe.dev')
Your example data
Create a SpatVector and a SpatRaster
Apply the
rasterizeGeom
method to each line