Reputation: 303
I am working with Landsat imagery to calculate net radiation. There are very low negative values (ex: -0.000003) that are in my converted reflectance raster layers. I want to make sure that my reflectances are 0 - 1 in order to reduce error in my future calculations.
How can I replace raster values less than 0 to "NA" in R. Similar to a raster calc function. I'm unsure how to provide an example, but I'm certain one of you could help me, yes?
Here is my equation for the reflectivity derived from Bastiaanssen et al. (1998)
Assuming, the pb1 indicates the reflectance for band 1 of Landsat, pi = 3.14..., lb1 = radiance for band 1, ESUN = exoatmospheric value for band 1, dr = the relative earth sun distance for the day of year.
#Calculate reflectivity per band. QC: Always 0 to 1
pb1 = (pi * lb1)/(ESUN1 * cos(solzen) * dr)
After this raster is created, all I want to do is set the pb1 values that are less than 0 to NA.
Help?
Upvotes: 20
Views: 53275
Reputation: 47706
With the terra
package, the memory-safe way to do this is to use classify
clamp
, or ifel
library(terra)
r <- rast(ncol=10, nrow=10)
values(r) <- rnorm(100)
x <- clamp(r, 0, values=FALSE)
y <- classify(r, cbind(-Inf, 0, NA), right=FALSE)
z <- ifel(r < 0, NA, r)
These methods are memory-safe and you can also provide a filename argument so that you do not need to call writeRaster
afterwards.
You can use app
but that is a bit clumsy and much less efficient
a <- app(r, function(x) { x[x<0] <- NA; x })
Approaches like this are nice for interactive exploration with small data sets, but they should generally not be used in "production" code.
r[r < 0] <- NA
Upvotes: 9
Reputation: 47706
With the raster
package, the memory-safe way to do this is to use reclassify
or clamp
library(raster)
r <- raster(ncol=10, nrow=10)
values(r) <- rnorm(100)
x <- clamp(r, useValues=FALSE)
y <- reclassify(r, cbind(-Inf, 0, NA), right=FALSE)
Note the right=FALSE
to not set cells that are zero to NA
.
These methods are memory-safe and you can also provide a filename argument so that you do not need to call writeRaster
afterwards.
Upvotes: 37
Reputation: 8893
raster::clamp
is an easy and flexible way to do this. One can set everything above and/or below threshold values to that threshold, or by setting useValues=FALSE
then values above/below are set to NA
. For example, lower values only:
r <- raster(ncol=3, nrow=3)
values(r) <- seq_len(9)
x <- clamp(r, lower=3, useValues=FALSE)
values(x)
# [1] NA NA 3 4 5 6 7 8 9
upper values only:
x <- clamp(r, upper=6, useValues=FALSE)
values(x)
# [1] 1 2 3 4 5 6 NA NA NA
and both upper and lower values:
x <- clamp(r, lower=3, upper=6, useValues=FALSE)
values(x)
# [1] NA NA 3 4 5 6 NA NA NA
Note the difference if useValues=TRUE
(the default):
x <- clamp(r, lower=3, upper=6)
values(x)
# [1] 3 3 3 4 5 6 6 6 6
Using raster_2.8-19
in this example.
Upvotes: 8
Reputation: 121
Another option is
pb1 <- raster::calc(pb1, function(x){x[x<0]<-NA; return(x)})
Upvotes: 0
Reputation: 93891
library(raster)
values(pb1)[values(pb1) < 0] = NA
Or, as suggested by @jbaums:
pb1[pb1 < 0] <- NA
If you want to keep the original raster object, remember to assign the original raster to a new object name before running the code above.
Upvotes: 32