How to Change the Resolution of a Raster Layer in R

How to change the resolution of a raster layer in R

You can use aggregate or disaggregate.

library(raster)

#get some sample data
data(meuse.grid)
gridded(meuse.grid) <- ~x+y
meuse.raster <- raster(meuse.grid)
res(meuse.raster)
#[1] 40 40

#aggregate from 40x40 resolution to 120x120 (factor = 3)
meuse.raster.aggregate <- aggregate(meuse.raster, fact=3)
res(meuse.raster.aggregate)
#[1] 120 120

#disaggregate from 40x40 resolution to 10x10 (factor = 4)
meuse.raster.disaggregate <- disaggregate(meuse.raster, fact=4)
res(meuse.raster.disaggregate)
#[1] 10 10

How to change resolution of 2 rasters layers in R?

Here is a self-contained, minimal, reproducible example:

library(raster)
bioclim <- raster(nrow=163, ncol=319, ext=extent(18.83337, 72.00005, 40.99999, 68.16666))
soil <- raster(nrow=1256, ncol=2213, ext=extent(20, 69.99999, 42.62224, 71))
values(soil) = 1:ncell(soil)

Solution: if you cannot use (dis-)aggregate, you can use resample

sb <- resample(soil, bioclim)
sb
#class : RasterLayer
#dimensions : 163, 319, 51997 (nrow, ncol, ncell)
#resolution : 0.1666667, 0.1666667 (x, y)
#extent : 18.83337, 72.00005, 40.99999, 68.16666 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +no_defs
#source : memory
#names : layer
#values : 284578.3, 2779484 (min, max)

Or use terra, if you need better performance:

library(terra)
bc <- rast(nrow=163, ncol=319, ext=ext(18.83337, 72.00005, 40.99999, 68.16666))
so <- rast(nrow=1256, ncol=2213, ext=ext(20, 69.99999, 42.62224, 71))
values(so) = 1:ncell(so)

sb <- resample(so, bc)

How does R assign a resolution to raster objects?

From what I understand from the vignette

The default settings will create a global raster data structure with a longitude/latitude coordinate reference system and 1 by 1 degree cells.

r
# class : RasterLayer
# dimensions : 18, 18, 324 (nrow, ncol, ncell)
# resolution : 20, 10 (x, y)
# extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
# coord. ref. : +proj=longlat +datum=WGS84

r x extent goes to from -180 to +180 degrees by default (a total of 360 degrees), and 360 degrees / 18 points = a x resolution of 20 degrees.

r y extent goes form -90 to +90 degrees by default, and 180 degrees / 18 points results in a y resolution of 10 degrees.

Matching the resolution of two rasters

Why would this Error: !is.null(fact) is not TRUE be odd? If you look at ?disaggregate you will see that there is no argument nrows, but there is a required argument fact, which you did not supply.

You can do

lc_r2a <- disaggregate (lc_r1, fact=12)

Or

lc_r2b <- disaggregate(lc_r1, fact=12, method='bilinear')

which is equivalent to

lc_r2c <- resample(lc_r1, r)

Why are you not sure that this is correct?

However, given that you want to mask lc_r1, the logical approach would be to go the opposite direction and change the resolution of your mask, r,

ra <- aggregate(r, fact=12, na.rm=TRUE) 
lcm <- mask(lc_r1, ra)

Resample raster

r_hr <- raster(nrow=70, ncol=70) #High resolution raster with categorical data
set.seed(0)
r_hr[] <- round(runif(1:ncell(r_hr), 1, 5))
r_lr <- raster(nrow=6, ncol=6)

r_hr
#class : RasterLayer
#dimensions : 70, 70, 4900 (nrow, ncol, ncell)
#resolution : 5.142857, 2.571429 (x, y)
#extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
#data source : in memory
#names : layer
#values : 1, 5 (min, max)

r_lr
#class : RasterLayer
#dimensions : 6, 6, 36 (nrow, ncol, ncell)
#resolution : 60, 30 (x, y)
#extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0

Direct aggregate is not possible, because 70/6 is not an integer.

dim(r_hr)[1:2] / dim(r_lr)[1:2]
#[1] 11.66667 11.66667

Nearest neighbor resampling is not a good idea either as the results would be arbitrary.

Here is a by layer approach that you suggested and dww also showed already.

b <- layerize(r_hr)
fact <- round(dim(r_hr)[1:2] / dim(r_lr)[1:2])
a <- aggregate(b, fact)
x <- resample(a, r_lr)

Now you have proportions. If you want a single class you could do

y <- which.max(x)

In that case, another approach would be to aggregate the classes

ag <- aggregate(r_hr, fact, modal) 
agx <- resample(ag, r_lr, method='ngb')

Note that agx and y are the same. But they can both be problematic as you might have cells with 5 classes with each about 20%, making it rather unreasonable to pick one winner.

Aggregate large raster to raster with lower resolution via mean (R)

The ratio of your resolutions turns out to be an exact integer:

res1 = 0.9/(60*60) # resolution converted to degrees
res2 = 0.5
res.factor = res2 / res1
res.factor
# [1] 2000

You can double check this with you actual rasters using res.factor = res(forest1) / res(dfr_2010_crop) - I can't do that because you did not provide a reproducible example.

This means that you can simply use raster::aggregate to change the resolution.

TreeCoverPercent = aggregate(forest1, res.factor)

In case your res.factor was not a precise integer, then you can still use this method by rounding to the nearest integer, followed by resampling to the final desired resolution.

TreeCoverPercent = aggregate(forest1, round(res.factor))
TreeCoverPercent = resample(TreeCoverPercent, dfr_2010_crop)


Related Topics



Leave a reply



Submit