Related
I am trying to align .asc rasters with different extents but same resolution in R so that they can be used to create a Raster stack. I am working with the "raster" package (Hijmans et al. 2022, version 3.5-29)
The rasters have the following properties:
> r1;r2
class : RasterLayer
dimensions : 1420, 1207, 1713940 (nrow, ncol, ncell)
resolution : 50, 50 (x, y)
extent : -30155.19, 30194.81, -35519.03, 35480.97 (xmin, xmax, ymin, ymax)
crs : NA
source : Naive_IS2018_UDScaled.asc
names : Naive_IS2018_UDScaled
class : RasterLayer
dimensions : 1418, 939, 1331502 (nrow, ncol, ncell)
resolution : 50, 50 (x, y)
extent : -23488.8, 23461.2, -35475.82, 35424.18 (xmin, xmax, ymin, ymax)
crs : NA
source : Naive_IS2019_UDScaled.asc
names : Naive_IS2019_UDScaled
In order to bring them to the same extent, I am creating a raster list and extract the minimum and maximum values:
## align all rasters to same extent
rasterlist <- as.list(r1,r2)
raster_extents <- lapply(rasterlist, raster::extent)
do.call(raster::merge, raster_extents)
sharedextent <- c(-30155.19 , 30194.81 , -35519.03 , 35480.97)
Now I am using the enxtend() to extend the extents of the rasters so that they share the same extents.
r1 <- raster::extend(r1, sharedextent)
r2 <- raster::extend(r2, sharedextent)
However, this does not result in a change of extents. But, it changes the source to "memory" and add a "values" row in r2.
> r1;r2
class : RasterLayer
dimensions : 1420, 1207, 1713940 (nrow, ncol, ncell)
resolution : 50, 50 (x, y)
extent : -30155.19, 30194.81, -35519.03, 35480.97 (xmin, xmax, ymin, ymax)
crs : NA
source : Naive_IS2018_UDScaled.asc
names : Naive_IS2018_UDScaled
class : RasterLayer
dimensions : 1420, 1207, 1713940 (nrow, ncol, ncell)
resolution : 50, 50 (x, y)
extent : -30138.8, 30211.2, -35525.82, 35474.18 (xmin, xmax, ymin, ymax)
crs : NA
source : memory
names : Naive_IS2019_UDScaled
values : 0, 0.0006528347 (min, max)
Any help would be greatly appreciated.
Is that you are looking for? (Updated with keepres = TRUE). Please keep in mind that changing extent will either change resolution, either number of rows/columns.
library(raster)
#> Loading required package: sp
r1 <- raster(nrows = 1420, ncols = 1207, resolution = 50, ext = extent(c(-30155.19, 30194.81, -35519.03, 35480.97)))
r2 <- raster(nrows = 1418, ncols = 939, resolution = 50, ext = extent(c(-23488.8, 23461.2, -35475.82, 35424.18)))
r2
#> class : RasterLayer
#> dimensions : 1418, 939, 1331502 (nrow, ncol, ncell)
#> resolution : 50, 50 (x, y)
#> extent : -23488.8, 23461.2, -35475.82, 35424.18 (xmin, xmax, ymin, ymax)
#> crs : NA
r2 <- setExtent(r2, r1, keepres=TRUE)
r2
#> class : RasterLayer
#> dimensions : 1420, 1207, 1713940 (nrow, ncol, ncell)
#> resolution : 50, 50 (x, y)
#> extent : -30155.19, 30194.81, -35519.03, 35480.97 (xmin, xmax, ymin, ymax)
#> crs : NA
Created on 2022-09-06 with reprex v2.0.2
My rasterlayer has a range from 0 to 1. I just want the Pixel values from 0.2 to 0.1
I tried this Code:
R<- myraster
R[(R<=0.1) & (R>=0.2)] <- NA
This is my idea for a range of value.
For a single value I don't know.
If I use this code I get online NA or the range from.0 to 1 does not change.
Is my Code wrong or is there another option?
I also used this one only to get the value 0.1
R<- myraster
R[(R<=0.1) & (R>=0.1)] <- NA
You can do it in two steps. For instance,
library(raster)
# Simulate raster
R <- raster(ncol=10, nrow=10)
values(R) <- runif(ncell(R))
#Subset the raster in two steps
R[R >= 0.2] <- NA
R[R <= 0.1] <- NA
R
Here's the output...
> R <- raster(ncol=10, nrow=10)
> values(R) <- runif(ncell(R))
> R
class : RasterLayer
dimensions : 10, 10, 100 (nrow, ncol, ncell)
resolution : 36, 18 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : memory
names : layer
values : 0.01307758, 0.9926841 (min, max)
> R[R>=0.2]<-NA
> R[R<=0.1 ]<-NA
> R
class : RasterLayer
dimensions : 10, 10, 100 (nrow, ncol, ncell)
resolution : 36, 18 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : memory
names : layer
values : 0.1008731, 0.1912601 (min, max)
I am using Sentinel-2 data to calculate the NDVI and the Enhanced Vegetation Index (EVI):
NDVI <- (B8 - B4) / (B8 + B4)
## Works great
EVI <- 2.5*(B8-B4)/((B8+6*B4-7.5*B2)+1)
## Wonky
B8, B4, and B2 are RasterLayers of the Sentinel 2 bands (B8 = VNIR, 10 m, 842 nm, B4...etc.):
These all look fine and work with the simpler NDVI calculation, even if I use B2 in place of B4 - it works.
The EVI hist(EVI) looks like I thought it should look, but I get a different result if I plot it again after recalculating:
A warning message also results now:
>hist(EVI)
Warning message:
In .hist1(x, maxpixels = maxpixels, main = main, plot = plot, ...) :
0% of the raster cells were used. 100000 values used.
The plot(EVI) legend is ramped from -1 to 5, but the values do not seem to match up:
maxValue(EVI)
#[1] 3199.469
minValue(EVI)
#[1] -1370.398
quantile(EVI, probs = c(0.25,0.5,0.75))
# 25% 50% 75%
#0.2694335 0.3377984 0.4481901
EVI
#class : RasterLayer
#dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
#resolution : 10, 10 (x, y)
#extent : 399960, 509760, 6190200, 6300000 (xmin, xmax, ymin, ymax)
#crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs
#source : r_tmp_2022-04-14_170725_107992_82859.grd
#names : layer
#values : -1370.398, 3199.469 (min, max)
QUESTION: Why would the EVI values be so high? I would expect a maxValue to be slightly >1 minValue to be slightly <-1. NDVI looks okay:
NDVI
#class : RasterLayer
#dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
#resolution : 10, 10 (x, y)
#extent : 399960, 509760, 6190200, 6300000 (xmin, xmax, ymin, ymax)
#crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs
#source : r_tmp_2022-04-14_162459_107992_94886.grd
#names : layer
#values : -2.4375, 0.9981395 (min, max)
If I manually plug the EVI values:
> EVI_Max = 2.5 * ((maxValue(B8) - maxValue(B4)) / ((maxValue(B8) + (6*maxValue(B4)) - (7.5*maxValue(B2))) + 1))
> EVI_Max
[1] 0.1979678
> EVI_Maxb = 2.5 * ((maxValue(B8) - maxValue(B4)) / ((minValue(B8) + (6*minValue(B4)) - (7.5*minValue(B2))) + 1))
> EVI_Maxb
[1] 0.8300415
> EVI_Maxc = 2.5 * ((minValue(B8) - minValue(B4)) / ((maxValue(B8) + (6*maxValue(B4)) - (7.5*maxValue(B2))) + 1))
> EVI_Maxc
[1] 0
The input raster data (this has been run as brick and stack - same results):
B8 <- raster(sen_complete, layer=7)/10000 ##Layer7=B8
B4 <- raster(sen_complete, layer=3)/10000 ##Layer3=B4
B2 <- raster(sen_complete, layer=1)/10000 ##Layer1=B2
> sen_complete
class : RasterBrick
dimensions : 10980, 10980, 120560400, 8 (nrow, ncol, ncell, nlayers)
resolution : 10, 10 (x, y)
extent : 399960, 509760, 6190200, 6300000 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs
source : r_tmp_2022-04-14_102523_107992_02726.grd
names : layer.1, layer.2, layer.3, layer.4, layer.5, layer.6, layer.7, layer.8
min values : 1, 1, 1, 1, 1, 0, 1, 1
max values : 7580, 8784, 12208, 12040, 14475, 15740, 15528, 15605
B8
#class : RasterLayer
#dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
#resolution : 10, 10 (x, y)
#extent : 399960, 509760, 6190200, 6300000 (xmin, xmax, ymin, ymax)
#crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs
#source : r_tmp_2022-04-14_172529_107992_50061.grd
#names : layer.7
#values : 1e-04, 1.5528 (min, max)
B4
#class : RasterLayer
#dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
#resolution : 10, 10 (x, y)
#extent : 399960, 509760, 6190200, 6300000 (xmin, xmax, ymin, ymax)
#crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs
#source : r_tmp_2022-04-14_172558_107992_74998.grd
#names : layer.3
#values : 1e-04, 1.2208 (min, max)
B2
#class : RasterLayer
#dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
#resolution : 10, 10 (x, y)
#extent : 399960, 509760, 6190200, 6300000 (xmin, xmax, ymin, ymax)
#crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs
#source : r_tmp_2022-04-14_172617_107992_52307.grd
#names : layer.1
#values : 1e-04, 0.758 (min, max)
s <- stack(B2, B4, B8)
> s
class : RasterStack
dimensions : 10980, 10980, 120560400, 3 (nrow, ncol, ncell, nlayers)
resolution : 10, 10 (x, y)
extent : 399960, 509760, 6190200, 6300000 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs
names : layer.1, layer.3, layer.7
min values : 1e-04, 1e-04, 1e-04
max values : 0.7580, 1.2208, 1.5528
The output for visual comparison:
> par(mfrow=c(2,1))
> plot(NDVI)
> plot(EVI)
Recreate with random data:
> rtest_B8 <- raster(ncol=10980, nrow=10980)
> rtest_B4 <- raster(ncol=10980, nrow=10980)
> rtest_B2 <- raster(ncol=10980, nrow=10980)
> minValue(raster(sen_complete, layer=7))
[1] 1
> maxValue(raster(sen_complete, layer=7))
[1] 15528
> minValue(raster(sen_complete, layer=3))
[1] 1
> maxValue(raster(sen_complete, layer=3))
[1] 12208
> minValue(raster(sen_complete, layer=1))
[1] 1
> maxValue(raster(sen_complete, layer=1))
[1] 7580
> set.seed(0)
> values(rtest_B8) <- runif(ncell(rtest), min = (minValue(raster(sen_complete, layer=7))), max = maxValue(raster(sen_complete, layer=7)))
> set.seed(999)
> values(rtest_B4) <- runif(ncell(rtest), min = (minValue(raster(sen_complete, layer=3))), max = maxValue(raster(sen_complete, layer=3)))
> set.seed(-999)
> values(rtest_B2) <- runif(ncell(rtest), min = (minValue(raster(sen_complete, layer=1))), max = maxValue(raster(sen_complete, layer=1)))
> rtest_B8 <- rtest_B8/10000
> rtest_B4 <- rtest_B4/10000
> rtest_B2 <- rtest_B2/10000
> EVI_test <- 2.5*(rtest_B8-rtest_B4)/((rtest_B8+6*rtest_B4-7.5*rtest_B2)+1)
> plot(EVI_test)
> EVI_test
class : RasterLayer
dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
resolution : 0.03278689, 0.01639344 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : r_tmp_2022-04-15_132504_107992_89378.grd
names : layer
values : -8154455, 6779455 (min, max)
> NDVI_test <- (rtest_B8 - rtest_B4) / (rtest_B8 + rtest_B4)
> plot(NDVI_test)
> NDVI_test
class : RasterLayer
dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
resolution : 0.03278689, 0.01639344 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : r_tmp_2022-04-15_132601_107992_94720.grd
names : layer
values : -0.9998338, 0.9998693 (min, max)
> hist(EVI_test)
Warning message:
In .hist1(x, maxpixels = maxpixels, main = main, plot = plot, ...) :
0% of the raster cells were used. 100000 values used.
> hist(NDVI_test)
Warning message:
In .hist1(x, maxpixels = maxpixels, main = main, plot = plot, ...) :
0% of the raster cells were used. 100000 values used.
> i1 <- which.max(EVI_test)
> s1 <- stack(rtest_B2, rtest_B4, rtest_B8)
> s <- stack(B2, B4, B8)
> s1[i1]
layer.1 layer.2 layer.3
[1,] 0.3627138 0.06103937 1.354118
> i2 <- which.max(EVI)
> s[i2]
NULL
> i3 <- which.max(NDVI)
> s[i3]
layer.1 layer.3 layer.7
[1,] 1e-04 1e-04 0.1074
> i4 <- which.max(NDVI_test)
> s1[i4]
layer.1 layer.2 layer.3
[1,] 0.3392011 0.0001000134 1.53007
> which.max(values(EVI))
[1] 73288066
> which.min(values(EVI))
[1] 103184643
Adding image of zoom and click in search of max EVI, but it does not look like there is anything greater than 1.113 - that is the highest number I have.
This formula
EVI <- 2.5*(B8-B4)/((B8+6*B4-7.5*B2)+1)
Suggests that the denominator could be very small and that would lead to a large EVI. But there is no reason to assume that the max EVI will be reached when all the Bs are at their maximum value.
What I would do is find the cell with the maximum EVI value, and then look at the input values in that cell. Perhaps like this
i <- which.max(EVI)
s <- stack(B2, B4, B8)
s[i]
I solved this issue after re-writing my script using the newer terra package; updating my code from the raster package. The terra package provided the solution with: resample {terra}
The notes state: "near: nearest neighbor...It is not a good choice for continuous values. This is used by default if the first layer of x is categorical."
My issue was tied to the Sentinel-2 Scene Classification (SCL) and Cloud (Cld) classification layers, which are categorical data:
1: Saturated defective, 2: Dark feature shadow, 3: Cloud shadow, 4: Vegetation, 5: Not vegetated, 6: Water, 7: Unclassified, 8: Cloud medium probability, 9: Cloud high probability, 10: Thin cirrus, 11: Snow ice.
The raster resample calculation I used was calling method=bilinear. This converted the discrete (factor / categorical) to continuous data and caused the errors to follow in the masking process. The coding was repaired by using method=near and class: SpatRaster.
Suppose one runs the following R code
install.packages("raster")
library(raster)
r <- raster(ncol=18, nrow=18)
res(r)
The output of the res function is
[1] 20 10
How are these values defined? How does the raster function calculate them? In what units are they expressed?
As pointed out by Guillaume Devailly, the horizontal resolution is the horizontal extent divided by the number of columns. The vertical resolution is the vertical extent divided by the number of rows. The units are the units of your coordinate reference system. The default is degrees (for longitude/latitude). To add more to Guillaume's answer:
Create a raster with 10 rows and columns that goes from 0 to 10. The resolution is 1.
library(raster)
r <- raster(ncol=10, nrow=10, xmn=0, xmx=10, ymn=0, ymx=10)
r
#class : RasterLayer
#dimensions : 10, 10, 100 (nrow, ncol, ncell)
#resolution : 1, 1 (x, y)
#extent : 0, 10, 0, 10 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
Change the resolution to 0.5; the number of rows and columns double
res(r) <- 0.5
r
#class : RasterLayer
#dimensions : 20, 20, 400 (nrow, ncol, ncell)
#resolution : 0.5, 0.5 (x, y)
#extent : 0, 10, 0, 10 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
You can change the resolution indirectly by adjusting the extent
extent(r) <- c(0,5,0,5)
r
#class : RasterLayer
#dimensions : 20, 20, 400 (nrow, ncol, ncell)
#resolution : 0.25, 0.25 (x, y)
#extent : 0, 5, 0, 5 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
The x and y resolution can be set to a different value
res(r) <- c(1, 0.5)
When you change the resolution directly, via res any cell values associated with the Raster* object are lost; because the number of rows or columns has to change. If you change it indirectly, by changing the extent, the values stay.
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.
I am trying to calculate the mean of a rasterbrick over specific timesteps in R.
Subsetting the dataset shows a lay-out that appears to be correct (to me), however R does not allow any computations to follow up.
> r_sub <- b[[1699:1862]]
> r_sub
class : RasterStack
dimensions : 127, 147, 18669, 164 (nrow, ncol, ncell, nlayers)
resolution : 5, 5 (x, y)
extent : 603299.4, 604034.4, 6615598, 6616233 (xmin, xmax, ymin, ymax)
crs : NA
names : X2019.02.09.19, X2019.02.09.20, X2019.02.09.21, X2019.02.09.22, X2019.02.09.23, X2019.02.09.24, X2019.02.10.1, X2019.02.10.2, X2019.02.10.3, X2019.02.10.4, X2019.02.10.5, X2019.02.10.6, X2019.02.10.7, X2019.02.10.8, X2019.02.10.9, ...
> r_mean <- calc(r_sub, mean)
Error in Rsx_nc4_get_vara_double: NetCDF: Index exceeds dimension bound
Var: SWIT Ndims: 3 Start: 1698,0,0 Count: 1,127,147
Error in ncvar_get_inner(ncid2use, varid2use, nc$var[[li]]$missval, addOffset, :
C function R_nc4_get_vara_double returned error
How to solve this specific error?
I am guessing that this is related to a problem with your file, not with the code.
I did this and it worked well
library(raster)
b <- brick("filename.nc")
r_sub <- b[[1699:1862]]
r_sub
#class : RasterStack
#dimensions : 160, 320, 51200, 164 (nrow, ncol, ncell, nlayers)
#resolution : 1.125, 1.121277 (x, y)
#extent : -0.5625, 359.4375, -89.70216, 89.70216 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
mean(r_sub)
#class : RasterLayer
#dimensions : 160, 320, 51200 (nrow, ncol, ncell)
#resolution : 1.125, 1.121277 (x, y)
#extent : -0.5625, 359.4375, -89.70216, 89.70216 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
#source : memory
#names : layer
#values : 3.033032e-07, 0.0002482847 (min, max)
Also, you might want to look into using stackApply