Combining 2 raster data sets with different extent, resolution and point regularity - raster

I'm having trouble merging two raster datasets that have different resolution and extent, and have irregular point data. Below is info on each raster. I need these datasets to merge according to the grid points so that I can run a fire spread model (which requires both wind and slope data).
I have tried converting to normal dataframes (using rasterToPoints) before merging but the differences lead to loss of a lot of grid points.
I have tried to align the rasters with project raster and rasterize, but I haven't managed to get it to work. If anyone has an idea that could help, I would really appreciate your answer!
'''
Data from https://globalwindatlas.info/downloads/gis-files
> wind <- raster("ZAF_wind-speed_10m.tif"); wind
class : RasterLayer
dimensions : 11271, 11804, 133042884 (nrow, ncol, ncell)
resolution : 0.0025, 0.0025 (x, y)
extent : 13.33407, 42.84407, -50.31423, -22.13673 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : C:/Users/s2000128/Documents/Flammability modelling/ZAF/ZAF_wind-speed_10m.tif
names : ZAF_wind.speed_10m
Data from https://datacatalog.worldbank.org/dataset/world-slope-model
> slope <- raster("ZAF1_msk_alt.grd"); slope
class : RasterLayer
dimensions : 1548, 1992, 3083616 (nrow, ncol, ncell)
resolution : 0.008333333, 0.008333333 (x, y)
extent : 16.4, 33, -34.9, -22 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +ellps=WGS84 +no_defs
source : C:/Users/s2000128/Documents/Flammability modelling/slope_deg_0/slope_deg/ZAF1_msk_alt.grd
names : ZAF1_msk_alt
values : -26, 3264 (min, max)
Here are some examples of what I have tried:
1
windresampled <- projectRaster(wind,slope,method = 'ngb'); windresampled
2
wind_points <- rasterToPoints(wind);
coordinates(wind_points) = ~x+y;
proj4string(wind_points) = CRS("+init=epsg:4326");
gridded(wind_points) = TRUE;
g_wind <- raster(wind_points); g_wind;
extent(wind) <- c(16.4,33, -34.9,-22);
res(wind) <- c(0.0025, 0.0025);
r_wind <- rasterize(wind_points, g_wind, field = wind_points$z, fun = mean, na.rm = TRUE); r_wind

Related

R language, unreasonable (?) raster resolutions

Sorry for the very stupid question, but I'm really stuck here... I need to create a Digital Elevation Model for my study area. For this, I downloaded an SRTM (1 arc-seg resolution, freely available from the net) image, which comprises a region wider than my area of interest. The original raster has these characteristics:
class : RasterLayer
dimensions : 3601, 3601, 12967201 (nrow, ncol, ncell)
resolution : 0.0002777778, 0.0002777778 (x, y)
extent : -45.00014, -43.99986, -22.00014, -20.99986 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : s22_w045_1arc_v3.tif
names : s22_w045_1arc_v3
values : -32768, 32767 (min, max)
I need to (1) increase the resolution (initially of 30.75662 * 28.68392 m) to 1 * 1 m (that is, I really do not care about the exactitude of the elevations) and (2) crop a squared area of 2000 * 2000 m centered at a given coordinate. So, the first step I'm following is to re-project to UTM:
projection(r) <- "+proj=utm +zone=23 +datum=WGS84"
But the resolution units do not change after that:
class : RasterLayer
dimensions : 3601, 3601, 12967201 (nrow, ncol, ncell)
resolution : 0.0002777778, 0.0002777778 (x, y)
extent : -45.00014, -43.99986, -22.00014, -20.99986 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=23 +datum=WGS84 +units=m +no_defs
source : s22_w045_1arc_v3.tif
names : s22_w045_1arc_v3
values : -32768, 32767 (min, max)
If I try to set the resolutions in meters manually, then generates an empty raster. Can anybody be so kind as to throw some light on me here?
You are changing (i.e. overwriting) the CRS, not projecting the raster. Usually, it is recommended to create a template raster with the CRS and the resolution you need and reproject the raster using this template.
See here an example, I am switching to terra for the analysis since it is a newer and faster package, but I would show also how to convert it back to raster format:
library(raster)
#> Loading required package: sp
# Faking your data
r <- raster(
nrows = 3601, ncols = 3601,
ext = extent(c(-45.00014, -43.99986, -22.00014, -20.99986))
)
values(r) <- seq(-32768, 32767, length.out = ncell(r))
r
#> class : RasterLayer
#> dimensions : 3601, 3601, 12967201 (nrow, ncol, ncell)
#> resolution : 0.0002777784, 0.0002777784 (x, y)
#> extent : -45.00014, -43.99986, -22.00014, -20.99986 (xmin, xmax, ymin, ymax)
#> crs : +proj=longlat +datum=WGS84 +no_defs
#> source : memory
#> names : layer
#> values : -32768, 32767 (min, max)
plot(r)
# End of faking data
# Change to terra, much faster
library(terra)
#> terra 1.5.21
r_terra <- terra::rast(r)
template <- terra::project(r_terra, "+proj=utm +zone=23 +datum=WGS84")
# Change to the desired res
res(template) <- c(2000, 2000)
# Reproject
r_terra_reproj <- terra::project(r_terra, template)
r_terra_reproj
#> class : SpatRaster
#> dimensions : 56, 52, 1 (nrow, ncol, nlyr)
#> resolution : 2000, 2000 (x, y)
#> extent : 499985.4, 603985.4, -2433195, -2321195 (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=utm +zone=23 +datum=WGS84 +units=m +no_defs
#> source : memory
#> name : layer
#> min value : -32371.95
#> max value : 32182.81
terra::plot(r_terra_reproj)
# Back to RasterLayer
r_reproj <- raster(r_terra_reproj)
r_reproj
#> class : RasterLayer
#> dimensions : 56, 52, 2912 (nrow, ncol, ncell)
#> resolution : 2000, 2000 (x, y)
#> extent : 499985.4, 603985.4, -2433195, -2321195 (xmin, xmax, ymin, ymax)
#> crs : +proj=utm +zone=23 +datum=WGS84 +units=m +no_defs
#> source : memory
#> names : layer
#> values : -32371.95, 32182.81 (min, max)
Created on 2022-06-10 by the reprex package (v2.0.1)

terra function to extract all bands of one variable? (equivalent to brick('x', varname='y'))

I have a netcdf file that contains 79 variables, and for each variable there are 365 bands (one for each day of the year). I want to read all bands of one variable (i.e., a raster with 365 ayers). With the 'raster' package this would work as follows:
dailyvalues <- brick('GLOBAL_2010_day.nc', varname ='WDEP_PREC')
Result is a RasterBrick with 365 layers:
> dailyvalues
class : RasterBrick
dimensions : 180, 360, 64800, 365 (nrow, ncol, ncell, nlayers)
resolution : 1, 1 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : GLOBAL_2010_day.nc
names : X2010.01.01, X2010.01.02, X2010.01.03, X2010.01.04, X2010.01.05, X2010.01.06, X2010.01.07, X2010.01.08, X2010.01.09, X2010.01.10, X2010.01.11, X2010.01.12, X2010.01.13, X2010.01.14, X2010.01.15, ...
Date : 2010-01-01, 2010-12-31 (min, max)
varname : WDEP_PREC
But I haven't suceeded to do this with the 'terra' package. I tried
dailyvalues <- rast('GLOBAL_2010_day.nc')
> dailyvalues
class : SpatRaster
dimensions : 180, 360, 28835 (nrow, ncol, nlyr)
resolution : 1, 1 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs
sources : GLOBAL_2010_day.nc:WDEP_PREC (365 layers)
GLOBAL_2010_day.nc:WDEP_SOX (365 layers)
GLOBAL_2010_day.nc:WDEP_OXN (365 layers)
... and 76 more source(s)
varnames : WDEP_PREC (WDEP_PREC)
WDEP_SOX (WDEP_SOX)
WDEP_OXN (WDEP_OXN)
...
names : WDEP_PREC_1, WDEP_PREC_2, WDEP_PREC_3, WDEP_PREC_4, WDEP_PREC_5, WDEP_PREC_6, ...
unit : mm, mm, mm, mm, mm, mm, ...
time : 2010-01-01 18:00:00 to 2010-12-31 12:00:00
The resulting SpatRaster has 79 'sources', but what is the syntax to use if I want to extract one 'source'? Adding varname = 'WDEP_PREC' in the rast function doesn't work. I tried dailyvalues$... but that calls single layers only (as listed under 'names').
The argument to use is called subds in terra.
dailyvalues = rast("GLOBAL_2010_day.nc", subds="WDEP_PREC")
You should be able to do (as #dww says)
dailyvalues = rast("GLOBAL_2010_day.nc", subds="WDEP_PREC")
Or you can make a SpatRasterDataset
x = sds("GLOBAL_2010_day.nc")
And then extract the sub-dataset you want with
r <- x["WDEP_PREC"]
or
r <- x[1]
Furthermore, you can do
r <- rast('NETCDF:"GLOBAL_2010_day.nc:WDEP_PREC":WDEP_PREC')
(for the above to work you may need to add the path to the filename, or set your working directory to where it is)

How to mask or clip rasters in R?

I am working with a marine species that has a shallow distribution, and I would like to delimit modelling of several ascii layers (e.g.SST, SSS) to a 50m depth threshold along the coastline using a bathymetric dataset (e.g. Bio-Oracle, MARSPEC or GEBCO). I am working in R. I do not want bathymetry to be part of the model though.
Does anyone know how to do this?
This is the bathymetric raster (with values down to 100m depth):
class : RasterLayer
dimensions : 600, 420, 252000 (nrow, ncol, ncell)
resolution : 0.08333333, 0.08333333 (x, y)
extent : -20, 15, 10, 60 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : bathy
values : -100, -1 (min, max)
AND THIS IS RASTER STACK
class : RasterStack
dimensions : 600, 420, 252000, 4 (nrow, ncol, ncell, nlayers)
resolution : 0.08333333, 0.08333333 (x, y)
extent : -20, 15, 10, 60 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
names : SST.min, SST.max, SST.range, BO_dissox
min values : -0.120, 10.940, 0.000, 4.052
max values : 26.640, 30.320, 21.460, 8.058
Cheers,
Rita
library(raster)
library(marmap)
library(rgdal)
# your coordinate reference setup
this_crs <- crs("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
this_extent <- extent(-20, 15, 10, 60)
# a simple raster stack for example purpose
r <- raster(ncol=420, nrow=600, ext = this_extent, crs = this_crs)
values(r) <- (1:ncell(r))/100
r_SST <- sin(r)
r_SSS <- r + runif(ncell(r), 0, 100)^2
r_stack <- stack(r_SST, r_SSS)
# Get some sample bathymetric data to match your stack
# the marmaps package is handy but you could use your own
download_bathy <- getNOAA.bathy(-20, 15, 10, 60, res = 5, keep = TRUE)
bath_mask <- marmap::as.raster(download_bathy)
bath_mask <- projectRaster(from = bath_mask, to = r_stack)
# clip your raster stack to the desired bathymetric limits
bath_mask[bath_mask > 0 | bath_mask < -50] <- NA
clipped_stack <- mask(r_stack, bath_mask)
# check the result with a plot
plot(clipped_stack)
First use SDMPlay:::delim.area in which the first layer of the stack is used to delimit the 100m depth.
Then isolate the bathymetry layer with subset.
User raster:::mask to delimit all rasters to bathymetric area.
And finally remove bathymetry from stack, raster:::dropLayer.
Thanks to all and specially to Guillaumot Charlene!
Rita

Strange issue changing extent projection from UTM to latlon (WGS84) and back again to UTM

I'm trying the following procedure (I apologize for mistakes but it is the very first time here). I've the raster dtm.temp expressed as follows:
> dtm.temp
class : RasterLayer
dimensions : 668, 965, 644620 (nrow, ncol, ncell)
resolution : 64.9, 92.6 (x, y)
extent : 437230.1, 499858.6, 5138842, 5200699 (xmin, xmax, ymin, ymax)
coord. ref. : +init=epsg:32632 +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : elev
values : 362.8404, 3584.865 (min, max)
Using this extent I convert it in longlat in the following way
# I build a spatial dataframe with extent data from dtm.temp
df <- data.frame(ID = 1:2, X = c(dtm.temp#extent#xmin, dtm.temp#extent#xmax),
Y = c(dtm.temp#extent#ymin, dtm.temp#extent#ymax))
coordinates(df) <- c("X", "Y")
crs_text <- crs(dtm.temp, asText=TRUE) # extracting crs from dtm.temp
proj4string(df) <- CRS(crs_text)
ext.lonlat <- spTransform(df, CRS("+proj=longlat +datum=WGS84"))
ext.lonlat
> ext.lonlat
class : SpatialPointsDataFrame
features : 2
extent : 8.183449, 8.998142, 46.40024, 46.95982 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
variables : 1
names : ID
min values : 1
max values : 2
at this point I use the extent (expressed as longlat) to crop the following raster dtm.temp1 (always in longlat but with a different initial extent and higher resolution)
> dtm.temp1
class : RasterLayer
dimensions : 9956, 14656, 145915136 (nrow, ncol, ncell)
resolution : 0.0002777778, 0.0002777778 (x, y)
extent : 7.857917, 11.92903, 44.27042, 47.03597 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : elev
values : -18, 4543 (min, max)
then
dtm.temp1.crop <- crop(dtm.temp1, ext.lonlat)
> dtm.temp1.crop
class : RasterLayer
dimensions : 2015, 2933, 5909995 (nrow, ncol, ncell)
resolution : 0.0002777779, 0.0002777772 (x, y)
extent : 8.183473, 8.998195, 46.40014, 46.95986 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
and then I project again in UTM the raster cropped at the same extent (or at least, so I believed..)
# crs_text as defined above
dtm.temp1.crop.proj <- projectRaster(dtm.temp1.crop, crs=crs_text)
>dtm.temp1.crop.proj
class : RasterLayer
dimensions : 2033, 2968, 6033944 (nrow, ncol, ncell)
resolution : 21.2, 30.9 (x, y)
extent : 437083.4, 500005, 5138362, 5201182 (xmin, xmax, ymin, ymax)
coord. ref. : +init=epsg:32632 +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : elev
values : 360, 3603.655 (min, max)
as you can see the two extent dtm.temp (the starting one) e the final dtm.temp1.crop.proj seems to be too much different.
extent dtm.temp : 437230.1, 499858.6, 5138842, 5200699
extent dtm.temp1.crop.proj: 437083.4, 500005, 5138362, 5201182
The error (in meters) is:
> 437230.1 - 437083.4
[1] 146.7
> 499858.6-500005
[1] -146.4
> 5138842 - 5138362
[1] 480
> 5200699-5201182
[1] -483
I'm sure I'm doing something wrong but I'm going crazy trying to understand what...
Someone is so patient to help me? Thanks in advance!
I add some more information trying to clearify on the basis of the comment of Mike.
Using a different approach (easier but computationally time consuming) I follow this steps:
> dtm.temp.extent <- extent(dtm.temp) # is the extent fixed
> dtm.temp.extent
class : Extent
xmin : 437230.1
xmax : 499858.6
ymin : 5138842
ymax : 5200699
# then I project directly the second raster dtm.temp1 using the crs
# with projectRaster (very slow)
> dtm.temp1.proj <- projectRaster(dtm.temp1,crs=crs_text)
# then I crop to the fixed extent
> dtm.temp1.proj.crop <- crop(dtm.temp1.proj, dtm.temp.extent)
# this is what I obtain
> extent(dtm.temp)
class : Extent
xmin : 437230.1
xmax : 499858.6
ymin : 5138842
ymax : 5200699
> extent(dtm.temp1.proj.crop)
class : Extent
xmin : 437233.6
xmax : 499852
ymin : 5138857
ymax : 5200688
the error now appears to me very reasonable:
> 437230.1 - 437233.6
[1] -3.5
> 499858.6 - 499852
[1] 6.6
> 5138842 - 5138857
[1] -15
> 5200699 - 5200688
[1] 11
The reason of the first approach is only because I'm trying to speedup the code (very time consuming in the second approach).
(Edited) I add, it may be useful for someone, an image of the problem in the first workflow (the two points of the extent - LL and UR - far from raster even if on a different raster respect to the one above in the question) and the solution suggested by Mkennedy that works fine (using four points unprojecting all four corners of the raster, LL, UL, UR, LR and then taking the min/max of the 8 values). I was not catching the rotation that occurs when unprojecting to lat/lon using only the LL and UR coordinates. Taking the true min/max, the results are more closely (as in the 2nd workflow)
Position of the raster vertex following a different approach

Modifying and Masking Environmental Layers within specific asia area in R

I am trying to prepare the environmental layers (constrained in specific Asia area) for use in Maxent model. However, I ran into some error messages in the last line:
library(sp)
library(maptools)
library(rworldmap)
library(dismo)
# A specified range of Asia area that suitable for special species
tsta <- read.csv('CM10_Kop_Shp_V1.2/Asiaclip/Asiaclipt.csv',as.is=TRUE)[https://drive.google.com/file/d/0B4vIx9MCfJgfbHpINTlyUGZVbXc/view?usp=sharing][1]
tsta <- tsta[,seq(1,4)]
coordinates(tsta) = c("Lon", "Lat")
gridded(tsta) <- TRUE
ra <- raster(tsta)
# a Rasterstack contains global range of 40 bioclim variables
files3 <- list.files(path=paste
("CM10_1975H_Bio_ASCII_V1.2/CM10_1975H_Bio_V1.2"),
, pattern='txt',full.names=TRUE )[https://www.climond.org/Core/Authenticated/Data/CM10_V1.2/CM10_Bio_V1.2/CM10_Bio_ASCII_V1.2/CM10_1975H_Bio_ASCII_V1.2.zip][1]
predictors3 <- stack(files3)
asia.predictors3 <- mask(predictors3,ra)
Error in compareRaster(x, mask) : different extent
The details for predictors3 were
predictors3
class : RasterStack
dimensions : 857, 2160, 1851120, 40 (nrow, ncol, ncell, nlayers)
resolution : 0.1666667, 0.1666667 (x, y)
extent : -180, 180, -59.16667, 83.66667 (xmin, xmax, ymin, ymax)
coord. ref. : NA
names : CM10_1975H_Bio01_V1.2, CM10_1975H_Bio02_V1.2, CM10_1975H_Bio03_V1.2, CM10_1975H_Bio04_V1.2, CM10_1975H_Bio05_V1.2, CM10_1975H_Bio06_V1.2, CM10_1975H_Bio07_V1.2, CM10_1975H_Bio08_V1.2, CM10_1975H_Bio09_V1.2, CM10_1975H_Bio10_V1.2, CM10_1975H_Bio11_V1.2, CM10_1975H_Bio12_V1.2, CM10_1975H_Bio13_V1.2, CM10_1975H_Bio14_V1.2, CM10_1975H_Bio15_V1.2, ...
The details for ra were:
ra
class : RasterLayer
dimensions : 213, 290, 61770 (nrow, ncol, ncell)
resolution : 0.1666667, 0.1666667 (x, y)
extent : 97.5, 145.8333, 18.16667, 53.66667 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : in memory
names : Location
values : 168505, 377653 (min, max)
My goal is to prepare a RasterLayer or Rasterstack contains all variables of "predictors3" but limited in the range of "ra". As you can see the extent of ra was included in the extent of predictors3 and their resolutions were identical. How should I fix the error?
In this case, as the origin and resolution of ra and predictors3 are the same, you can use crop
predictors3 <- raster(xmn=-180, xmx=180, ymn=-59.16667, ymx=83.66667, res=1/6)
ra <- raster(xmn=97.5, xmx=145.8333, ymn=18.16667, ymx=53.66667, res=1/6)
x <- crop(predictors3, ra)
In other cases, you may need to use (dis)aggregate or resample
According to the above suggestions, I crop the the global climate layer "predictors3" to identify the extent of two rasters. Then, mask the latest raster to acquire the targeting variables limited in specific area.
asia.predictors <- crop(predictors3,ra)
asia.predictors3 <- mask(asia.predictors,ra)

Resources