Assign the value (1) to NA in tiff files - r

I have two raster files (values ranges from 0 to 1) and I want to find the difference between them. But the problem is there are certain values those are missing. So I want to assign them value 1 (Like NA=1). How can I do this? Any expert can solve this little query. Thanks
My code is this.
library(raster)
R1 <- raster ("D:/Results/1.tiff")
R2 <- raster ("D:/Results/2.tiff")
Se1= R2-R1
plot(Se1)

How large is your raster files and how limited by memory are you? With raster, the optimal memory safe approach when interacting with large files is to use the reclassify function shown below. Let me know if it works.
# Package names
library(raster)
# Read in files
R1 <- raster("D:/Results/1.tiff")
R2 <- raster("D:/Results/1.tiff")
# use the reclassify function to group values to other values.
# In this case, NA values to 1.Reclassification is done with matrix rcl ,
# in the row order of the reclassify table.
D1 <- reclassify(R1, cbind(NA, 1))
D2 <- reclassify(R2, cbind(NA, 1))
# Find the difference between the two and plot.
Se1 = R2-R1
plot(Se1)

Here is how you may do that with "terra" (the replacement of "raster")
library(terra)
R <- rast(paste0("D:/Results/", 1:2, ".tiff"))
R <- subst(R, NA, 1)
Se1 <- diff(R)

Related

How to create a new raster in terra with same NA cells?

I need to create some new rasters by assigning values using z <- rast(x, vals = y). I would like the new raster (z) to have NA values at the same location as the old raster (x), but with the newly assigned value(s) (y) in the non-NA cells.
What is the most efficient way to create a new raster with a matching NA pixels but with new values assigned to the non-NA pixels?
I don't see any argument to handle NA values listed in the documentation for rast(), so do I need to do a two step process where the value is first assigned to all cells and then NAs are transfered from the old raster to new?
In the following example I would like s to have the same outline as r but have a uniform value of 10 in the non-NA cells.
f <- system.file("ex/elev.tif", package="terra")
r <- rast(f)
s <- rast(r, vals=10) # This fill all rasters cells, including NAs
Here are four ways to do that:
library(terra)
f <- system.file("ex/elev.tif", package="terra")
r <- rast(f)
s1 <- classify(r, cbind(-Inf, Inf, 10))
s2 <- init(r, 10) |> mask(r)
s3 <- ifel(is.na(r), NA, 10)
s4 <- r * 0 + 10
I would expect approach 1 and 4 to be the most efficient.

Substitute pixels values of all layers in a raster stack

I would need help with raster stack.
I have a 365-layers raster stack (corresponding to an hydrological year) and I want to substitute the pixel with value 3 with the value of the last previous layer with different value.
For example, for a specific pixel I have the first 10 layers that give values:
1,1,2,3,3,3,3,2,1,1.
The layers where the value is 3 should be substituted with, in this case, 2, which is the last value, before the "3-window", different from 3.
This should be done for all layers (except, obviously, the first one) for each pixel.
Any idea?
I just convert my raster in a matrix and I work with matrices but this requires a lot of time.
Let's suppose that vel_3D_snow_P4 is my matrix (retrieved from raster) where I have 365 rows (days) and more than 400000 columns (pixels), I writed this code:
vel_3D_snow_P4_back=matrix(nrow=nrow(vel_3D_snow_P4),ncol=ncol(vel_3D_snow_P4))
for (i in 1:ncol(vel_3D_snow_P4)){
y <- which(vel_3D_snow_P4[,i]==3)
startIndex <- y[!(y-1) %in% y]
stopIndex <- y[!(y+1) %in% y]
matrix=matrix(nrow=length(startIndex),ncol=2)
matrix[,1]=startIndex
matrix[,2]=stopIndex
new_vector_back=vel_3D_snow_P4[,i]
for (j in 1:nrow(matrix)){
if (matrix[j,1]==1) next
new_vector_back[matrix[j,1]:matrix[j,2]]=new_vector_back[matrix[j,1]-1]
}
vel_3D_snow_P4_back=cbind(vel_3D_snow_P4_back,new_vector_back)
print(c("fine",toString(i)))
}
But, as you can imagine, with numerous pixels it is impossible! This is the reason why I was asking for a solution/idea by maintaining raster format (maybe using calc function?)
Thanks in advance.
Typically, the first step with problems like this is in R, is to write a function that operates on a vector. Or search for an existing one. My first google query pointed me to zoo::na.locf
library(zoo)
x <- c(1,1,2,3,3,3,3,2,1,1)
x[x==3] <- NA
na.locf(x)
# [1] 1 1 2 2 2 2 2 2 1 1
Then create example raster data
library(raster)
r <- raster(ncol=10, nrow=10)
s <- stack(lapply(c(1,2,3,3,4), function(i) setValues(r, i)))
And combine the two. You can do
A)
x <- reclassify(s, cbind(3, NA))
z <- calc(x, fun=na.locf)
or
B)
f <- function(v) {
v[v==3] <- NA
na.locf(v)
}
zz <- calc(s, f)

Removing NA rows raster

I have a raster with rows of NA that I want to remove in R. The rows are not on the edge of the raster, so I tried to use crop and trim but I didn't manage. Could someone give some tips please?
Here the file: https://drive.google.com/drive/folders/0B6-UFgI67v99c3ZhUFp0eWpzOGM
I do not see how that would make sense, conceptually. For a matrix, perhaps, but a raster does not have missing rows (even if the data might be stored in a sparse form, it would still know about them.)
Here is your problem:
library(raster)
r <- raster(nrow=10, ncol=10)
values(r) <- 1:ncell(r)
r[3:4, ] <- NA
You might think that this would do it:
rr <- is.na(r)
i <- which(rowSums(rr) != ncol(rr))
x <- r[i, ,drop=FALSE]
But that does not do what you want, because the raster returned would not be valid. I suppose you could use i in a loop and create a list of RasterLayer objects.
Finally, you can create a SpatialPointsDataFrame, which essentially is a sparse raster like this:
x <- as(r, 'SpatialPointsDataFrame')
But whether that is useful or not depends on what next you want to do with x

NA in clustering functions (kmeans, pam, clara). How to associate clusters to original data?

I need to cluster some data and I tried kmeans, pam, and clara with R.
The problem is that my data are in a column of a data frame, and contains NAs.
I used na.omit() to get my clusters. But then how can I associate them with the original data? The functions return a vector of integers without the NAs and they don't retain any information about the original position.
Is there a clever way to associate the clusters to the original observations in the data frame? (or a way to intelligently perform clustering when NAs are present?)
Thanks
The output of kmeans corresponds to the elements of the object passed as argument x. In your case, you omit the NA elements, and so $cluster indicates the cluster that each element of na.omit(x) belongs to.
Here's a simple example:
d <- data.frame(x=runif(100), cluster=NA)
d$x[sample(100, 10)] <- NA
clus <- kmeans(na.omit(d$x), 5)
d$cluster[which(!is.na(d$x))] <- clus$cluster
And in the plot below, colour indicates the cluster that each point belongs to.
plot(d$x, bg=d$cluster, pch=21)
This code works for me, starting with a matrix containing a whole row of NAs:
DF=matrix(rnorm(100), ncol=10)
row.names(DF) <- paste("r", 1:10, sep="")
DF[3,]<-NA
res <- kmeans(na.omit(DF), 3)$cluster
res
DF=cbind(DF, 'clus'=NA)
DF[names(res),][,11] <- res
print(DF[,11])

reclass values of multiple rasters with their names in R

I'm trying to make a reclassification of several raster files with R.
My raster files contain species ranges with the values of the total range in the occurring cells. The other cells have NoData. The files have their rank as name (1,2,3...).
Now I try to reclass the values of the cells where species occurs with the Rank.
I tried with for looping the reclassify function without success...
thanks in advance!
Let's say you have one raster representing the presence/absences of a single species. You also know the area extent and the range (expressed as occurrences) of this particular species. For each cell where this species is present you've filled it with the total occurrences.
Lets say this species was detected on 50 out of 400 cells.
The species occurrence expressed by presence on 50 random cells.
e1 <- extent(0,10,0,10)
r1 <- raster(extent(0,10,0,10))
res(r1) <- 0.5
r1[1:ncell(r1)] <- NA
r1[sample(ncell(r1), 50, rep = F)] <- 50
plot(r1)
But you may have this rasterLayer as a image file, stored at your disk and named with a rank of the species.
There are several ways to replace values in a rasterLayer. If for this particular species the rank is 1, you can replace the range by rank with
r1[!is.na(r1)] <- 1
If you want to lop over your file folder try this:
wdata <- '.../R/Stackoverflow/21876858' # your local folder
f.reclass <- function(x=x){
files <- list.files(file.path(wdata), all.files = F) # list all files from a given driver folder
# Assuming TIF images, List files from wdata folder
## Change below if using any other format
ltif <- grep(".tif$", files, ignore.case = TRUE, value = TRUE)
stkl <- stack()
for(i in 1:length(ltif)){
x <- raster(file.path(wdata, ltif[i]),
package = "raster", varname = fname)
rank <- as.numeric(sub("*.tif", "", ltif[i]))
# Change also here if not tif
stopifnot(is.numeric(rank)) # check for numeric
x[!is.na(x)] <- rank
stkl <- addLayer(stkl, x)
}
stkl
}
spreclass <- f.reclass(x=x)
You'll get a rasterStack object with your reclassified rasterLayers. your can unstack them, export, manipulate...

Resources