Problems with rasterize function in R - r

I have three SpatialPointsDataFrame objects that are actually just one point each. My intention is to make a raster for each of them with an extent that includes the point, in such a way that all cells but the point are "NA", so then I can use the distance() function in the package raster to generate a raster layer where the z value is the distance to the only cell in which z is not "NA".
My code works without problem with the first of the three objects, but the following error appears for the other two:
error in seq.default(zrng[1], zrng[2], length.out = cuts + 2) :
'from' cannot be NA, NaN or infinite
In addition: Warning messages:
1: In asMethod(object) :
complete map seems to be NA's -- no selection was made
2: In min(x) : no non-missing arguments to min; returning Inf
3: In max(x) : no non-missing arguments to max; returning -Inf
I have double and triple checked that my points are contained in the extent of the raster, and I really can't pinpoint the problem
Here's my code:
library(raster)
TIM <- data.frame()
TIM[1,1] <- -13.8309
TIM[1,2] <- 28.9942
VEN <- data.frame()
VEN[1,1] <- -15.7886
VEN[1,2] <- 27.8444
MCL <- data.frame()
MCL[1,1] <- -13.5325
MCL[1,2] <- 29.2914
coordinates(TIM) <- ~V1+V2
coordinates(VEN) <- ~V1+V2
coordinates(MCL) <- ~V1+V2
bb2 <- matrix(c(-20, -9.5, 20.5, 31.5), nrow = 2, ncol = 2, byrow = T)
bb2 <- extent(bb2)
r <- raster(nrows = 1217, ncols = 1047)
r <- setExtent(r, bb2, keepres=F)
rMCL <- rasterize(MCL, r)
spplot(rMCL)
#so far so good, but from now on it doesn't work
rVEN <- rasterize(VEN, r)
spplot(rVEN)
rTIM <- rasterize(TIM, r)
spplot(rTIM)
Edit: I have tried turning it to a SpatialGridDataFrame and I get to plot it but my point is not in the extent of the raster, i.e. the plot is empty. Code:
rr <- as(rTIM, "SpatialGridDataFrame")
spplot(rr)
#this produces an empty plot
I have also tried plotting it in a raster without a predetermined number of columns and rows, and it works:
r <- raster()
r <- setExtent(r, bb2, keepres=F)
rTIM <- rasterize(TIM, r)
spplot(rTIM)
# this produces a raster containing my point
The problem is, I really would need to set the resolution of the plot so each cell of the raster represents approx 1 squared km, which is what I get with the number of rows and columns I had previously used. Any ideas?

I can get it to work by adding all three sets of coordinates to the same dataframe and then using the count function when creating the raster:
library(raster)
# Add all 3 sets of coordinates to the same dataframe
df <- data.frame()
df[1,1] <- -13.8309
df[1,2] <- 28.9942
df[2,1] <- -15.7886
df[2,2] <- 27.8444
df[3,1] <- -13.5325
df[3,2] <- 29.2914
# Create new column in dataframe (we will use this for the count function)
df$x <- c(1,1,1)
# Convert to spatial points dataframe
df.sp <- df
coordinates(df.sp) <- ~ V1+V2
# Make raster
bb2 <- matrix(c(-20, -9.5, 20.5, 31.5), nrow = 2, ncol = 2, byrow = T)
bb2 <- extent(bb2)
r <- raster(nrows = 1217, ncols = 1047)
r <- setExtent(r, bb2, keepres=F)
# Rasterise using the count function
raster <- rasterize(df.sp, r, field= "x", fun="count")
# The table shows there are 3 cells with a value of 1 so it seems to have worked
table(values(raster))
1
3
spplot(raster)
raster
class : RasterLayer
dimensions : 1217, 1047, 1274199 (nrow, ncol, ncell)
resolution : 0.01002865, 0.00903862 (x, y)
extent : -20, -9.5, 20.5, 31.5 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : layer
values : 1, 1 (min, max)
The plot doesn't make a whole lot of sense to me but I think that's because you have a lot of cells in your raster so you can't really see anything. The values in the raster are definitely 3 cells with a value of 1 and all the rest are NA so I think this what you want.

Related

changing extent() to aggregate over a specfic grid of a RasterLayer

I am currently working with some data from Switzerland with 100x100 m resolution. I would like to aggregate the data to 1x1km from km-squares based on the national grid (with coordinates f.i. x = 500000, y = 130000), differing from the original extent of my RasterLayer object. I have provided some code for a RasterLayer based on the original extent (=r) and a RasterLayer with a new extent based on national grid cells in Switzerland (=r.agg) and plotted r.agg over r (the latter of, which I coloured in red to make the borders more obvious).
library(raster)
ncol <- 3677 # same as original RasterLayer
nrow <- 2261 # same as original RasterLayer
## create raster (with original extent)
r <- raster(ncol = ncol, nrow = nrow) # dimensions of raster
mat <- matrix(runif(ncol*nrow, 0,2), ncol = ncol, nrow = nrow) # write data
# create simplified country-borders / buffer
mat [0:100, 0:ncol] <- NA
mat [0:nrow, 0:100] <- NA
mat [(nrow - 100):nrow, 0:ncol] <- NA
mat [0:nrow, (ncol -100):ncol] <- NA
r[] <- mat #write data to raster
extent(r) <- matrix(c(479950, 73950, 847650, 300050), nrow = 2) # define extent
proj4string(r) <- "+proj=somerc +lat_0=46.95240555555556
+lon_0=7.439583333333333
+k_0=1 +x_0=600000 +y_0=200000
+ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0
+units=m +no_defs"
## create raster (with customised extent)
r.agg <- r # prepare aggregatable RasterLayer
extent(r.agg) <- matrix(c(480000, 74000, 847700, 300100), nrow = 2)
r.agg <- aggregate(r.agg, fact = 10, fun = mean)
par(bg = 'darkgrey')
plot(r, col = "red", legend = FALSE)
plot(r.agg, add = TRUE)
However, I am not entirely sure to interpret the results correctly:
The plotted "r.agg" over "r" shows a red line which I don't quite understand.
Option A (desired outcome): extent() allows me to aggregate over the national grid and aggregate over the spatially correct 100x100m information
Option B (which I hope does not happen): extent() will let me aggregate over the national grid, but using the data from the original grid and thus not the one from the correct 100x100 squares.
I didn't find the help page for extent() particularly helpful and would be glad to receive some clarification. If Option B is the case (or I misunderstood something completely), I would be really happy if someone could help me to figure this out. Thanks a lot in advance and sorry for my weird phrasing, I am new to analyzing spatial data.
The two rasters do not align, so you cannot rely on aggregate alone.
You can do
library(raster)
r <- raster(ncol = 3677, nrow = 2261, ext=extent(479950, 847650, 73950, 300050))
crs(r) <- "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=600000 +y_0=200000
+ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs"
r.agg <- raster(nrow=227, ncol=368, ext=extent(480000, 848000, 73100, 300100))
x <- resample(r, r.agg)
Or, to have more control
r.low <- disaggregate(r.agg, 10)
r.low <- resample(r, r.low)
ra <- aggregate(r.low, 10, mean)

Split RGB raster in multiples pieces and save file in GeoTiff with conditions

I've like to split a RGB raster in multiple pieces and save each image in GeoTiff format, but in the file name I need the count of points (pts) inside each piece. My code runs perfectly when I used a single raster image, but with stack or brick object doesn't work. I've like as final output in my directory nine GeoTiff files (I divided the original raster in 9 parts) with files names: SplitRas1points0.tif ... SplitRas9points0.tif
My code is:
#Packages
library(raster)
library(sp)
library(rgdal)
## Create a simulated RBG rasters
r <- raster(nc=30, nr=30)
r <- setValues(r, round(runif(ncell(r))* 255))
g <- raster(nc=30, nr=30)
g <- setValues(r, round(runif(ncell(r))* 255))
b <- raster(nc=30, nr=30)
b <- setValues(r, round(runif(ncell(r))* 255))
rgb<-stack(r,g,b)
plotRGB(rgb,
r = 1, g = 2, b = 3)
##Given interesting points coordinates
xd <- c(-24.99270,45.12069,99.40321,73.64419)
yd <- c(-45.435267,-88.369745,-7.086949,44.174530)
pts <- data.frame(xd,yd)
pts_s<- SpatialPoints(pts)
points(pts_s, col="black", pch=16)
# This function spatially aggregates the original raster
# it turns each aggregated cell into a polygon
# then the extent of each polygon is used to crop
# the original raster.
# The function returns a list with all the pieces
# it saves and plots each piece
# The arguments are:
# raster = raster to be chopped (raster object)
# ppside = pieces per side (integer)
# save = write raster (TRUE or FALSE)
# plot = do you want to plot the output? (TRUE or FALSE)
SplitRas <- function(raster,ppside,save,plot){
h <- ceiling(ncol(raster)/ppside)
v <- ceiling(nrow(raster)/ppside)
agg <- aggregate(raster,fact=c(h,v))
agg[] <- 1:ncell(agg)
agg_poly <- rasterToPolygons(agg)
names(agg_poly) <- "polis"
r_list <- list()
for(i in 1:ncell(agg)){
e1 <- extent(agg_poly[agg_poly$polis==i,])
r_list[[i]] <- crop(raster,e1)
}
if(save==T){
for(i in 1:length(r_list)){
writeRaster(r_list[[i]],filename=paste("SplitRas",i,sep=""),
format="GTiff",datatype="FLT4S",overwrite=TRUE)
}
}
if(plot==T){
par(mfrow=c(ppside,ppside))
for(i in 1:length(r_list)){
plot(r_list[[i]],axes=F,legend=F,bty="n",box=FALSE)
}
}
return(r_list)
}
#Slip RGB raster in 3 parts
splitRBG<-SplitRas(raster=rgb,ppside=3,save=FALSE,plot=FALSE)
Here OK a have 9 raster!!
[[1]]
class : RasterBrick
dimensions : 10, 10, 100, 3 (nrow, ncol, ncell, nlayers)
resolution : 12, 6 (x, y)
extent : -180, -60, 30, 90 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
source : memory
names : layer.1, layer.2, layer.3
min values : 0, 0, 2
max values : 249, 253, 252
...
[[9]]
class : RasterBrick
dimensions : 10, 10, 100, 3 (nrow, ncol, ncell, nlayers)
resolution : 12, 6 (x, y)
extent : 60, 180, -90, -30 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
source : memory
names : layer.1, layer.2, layer.3
min values : 3, 3, 3
max values : 254, 251, 248
#Count number of points inside each piece of raster
res<-NULL
for(i in 1:3){
pointcount = function(r, pts){
# make a raster of zeroes like the input
r2 = r
r2[] = 0
# get the cell index for each point and make a table:
counts = table(cellFromXY(r,pts))
# fill in the raster with the counts from the cell index:
r2[as.numeric(names(counts))] = counts
return(r2)
}
r2 = pointcount(splitRBG[i], pts_s)
res<-rbind(res,c(r2))
}
#
First problem, my stack object is considering a list and I have the output:
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘cellFromXY’ for signature ‘"list"’
#Run a code on each piece with the number of points inside each piece in the file name (res[i])
list2 <- list()
for(i in 1:3){ # 3 is the number of pieces
rx <- raster(paste("splitRBG",i,".tif",sep=""))
writeRaster(splitRBG,filename=paste("SplitRas",i,"points",res[i],sep=""),
format="GTiff",datatype="FLT4S",overwrite=TRUE)
}
#
Second problem, Ok if I don't have the numbers of point a cause of the error above, but my splitRBG object is don't recognise as RasterLayer, look my output:
Error in .rasterObjectFromFile(x, band = band, objecttype = "RasterLayer", :
Cannot create a RasterLayer object from this file. (file does not exist)
Any ideas please?
Now, I have rcount<-length(intersect(SpatialPoints(pts_s), r_list[[i]])) inside the first function and the problem is solved!!
SplitRas <- function(raster,ppside,save,plot){
h <- ceiling(ncol(raster)/ppside)
v <- ceiling(nrow(raster)/ppside)
agg <- aggregate(raster,fact=c(h,v))
agg[] <- 1:ncell(agg)
agg_poly <- rasterToPolygons(agg)
names(agg_poly) <- "polis"
r_list <- list()
for(i in 1:ncell(agg)){
e1 <- extent(agg_poly[agg_poly$polis==i,])
r_list[[i]] <- crop(raster,e1)
}
if(save==T){
for(i in 1:length(r_list)){
rcount<-length(intersect(SpatialPoints(pts_s), r_list[[i]])) #Count number of points inside each piece of raster
writeRaster(r_list[[i]],filename=paste(rcount,"_sample_",i,sep=""),
format="GTiff",datatype="FLT4S",overwrite=TRUE)
}
}
if(plot==T){
par(mfrow=c(ppside,ppside))
for(i in 1:length(r_list)){
plot(r_list[[i]],axes=F,legend=F,bty="n",box=FALSE)
}
}
return(r_list)
}
#Slip RGB raster in 3 parts
splitRBG<-SplitRas(raster=rgb,ppside=3,save=TRUE,plot=FALSE)
#

Grouping/stacking rasters from list of path and extract their min values for each group

I have a list of rasters path (rplist = 912 raster pathe for 912 rasters (19yeras)(12months)(4weeks)) as below:
[1] "C:/Users/Eric/Downloads/Results/RMI_2000_02_18.tif"
[2] "C:/Users/Eric/Downloads/Results/RMI_2000_02_26.tif"
[3] "C:/Users/Eric/Downloads/Results/RMI_2000_03_05.tif"
[4] "C:/Users/Eric/Downloads/Results/RMI_2000_03_13.tif"
[5] "C:/Users/Eric/Downloads/Results/RMI_2000_03_21.tif"
[...] "......"
[912] "C:/Users/Eric/Downloads/Results/RMI_2019_03_21.tif"
I need to read the rasters group them on monthly basis for each year (e.g. those belonging to RMI_2000_02) and then extract the minimum of each overlaying cell as a seperate raster (ignore NA values if any).
################### SETTING UP WORKING DIRECTORY ############################
setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
# list rasters in workin directory
rplist <- list.files(getwd(),full.names = TRUE)
From here I dont know what I can do with rs (as above) but shoudl be:
1. read rasters using rplist
2. group them by month for each year
3. extract the min raster
One way to do it is as below:
# list rasters in workin directory
rplist <- list.files(getwd(),full.names = TRUE)
r_name <- list.files(getwd(),full.names = FALSE)
# 1. read rasters using rplist
mrlist <- lapply(rplist, raster)
names(mrlist) <- r_name
# 2. stack rasters of the same month
tstList <- list()
tstStack <- stack()
i <- 1
for (y in 2000:2019){
for (m in 1:12){
# paste0(y,"_",sprintf("%02d", m)) returnes YEAR_MONTH
tstStack <- stack(mrlist[grep(paste0(y,"_",sprintf("%02d", m)), names(mrlist))] )
tstList[[i]] <- tstStack
i <- i+1
}
}
#3. extract the min raster(s)
min.rlist <- list()
for (i in 1:length(tstList)) {
min.rlist[[i]] <- min(tstList[[i]])
print(i) # to track the process
}
To get a good answer you should provide some example data (not an external file, use data that come with R, or create some with code). What you can do is create a RasterStack s and a vector v that groups the layers that need to be combined, and then do
x <- stackApply(s, v, fun=min, na.rm=TRUE)
Now with example data
library(raster)
# RasterStack with 12 layers
s <- stack(system.file("external/rlogo.grd", package="raster"))
s <- stack(s, s*2, s*3, s*4)
# make one layer with only NAs
values(s[[2]]) <- NA
# 12 corresponding dates
d <- paste0("RMI_2000", rep(sprintf("_%02d", 1:3), each=4), "_0", 1:4)
d
# [1] "RMI_2000_01_01" "RMI_2000_01_02" "RMI_2000_01_03" "RMI_2000_01_04" "RMI_2000_02_01" "RMI_2000_02_02" "RMI_2000_02_03" "RMI_2000_02_04" "RMI_2000_03_01" "RMI_2000_03_02" "RMI_2000_03_03" "RMI_2000_03_04"
# transform date into an index (stripping of the label and the week number)
i <- substr(d, 4, 11)
i
#[1] "2000_01" "2000_01" "2000_01" "2000_01" "2000_02" "2000_02" "2000_02" "2000_02" "2000_03" "2000_03" "2000_03" "2000_03"
ss <- stackApply(s, i, min, na.rm=TRUE)
ss
#class : RasterBrick
#dimensions : 77, 101, 7777, 3 (nrow, ncol, ncell, nlayers)
#resolution : 1, 1 (x, y)
#extent : 0, 101, 0, 77 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=merc +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
#data source : in memory
#names : index_2000_01, index_2000_02, index_2000_03
#min values : 0, 0, 0
#max values : 255, 510, 765

Error when using do.call to merge multi-band satellite image raster bricks in RStudio

I am attempting to merge some multi-band satellite images in R (unfortunately I can't share these due to copyright issues). They are of equal size and resolution with a slight overlap between them. When I import each image individually and merge them there is no issue:
library(raster)
raster1 <- brick("path/multi-band-raster1")
raster2 <- brick("path/multi-band-raster2")
raster3 <- brick("path/multi-band-raster3")
raster4 <- brick("path/multi-band-raster4")
raster5 <- brick("path/multi-band-raster5")
merged_scene <- merge(raster1, raster2, raster3, raster4, raster5)
However, I am aiming to make my code as flexible as possible so that I can reapply it to different sets of images. To do this I load the rasters as a list and then use the do.call() function so that the merge function takes all the arguments representing the raster bricks in the list:
folder <- paste0(getwd(),"/Images-folder/")
list.filenames <- list.files(folder, pattern=".tif$", full.names=FALSE)
list.data <- list()
for (i in 1:length(list.filenames)){
list.data[[i]] <- brick(paste0(folder,list.filenames[i]))
}
names(list.data) <- list.filenames
merged_scene <- do.call(merge, list.data)
However, when I run this I get:
Error in as.data.frame(x) : argument "x" is missing, with no default
Please let me know if you can see where I've gone wrong. Many thanks.
Don't give names to your bricks.
require(raster)
names(rlist) <- c("foo", "bar", "baz")
merged_scene <- do.call(merge, rlist)
# Error in as.data.frame(x) : argument "x" is missing, with no default
rlist <- list(raster1, raster2, raster3) # no names()
merged_scene <- do.call(merge, rlist)
merged_scene
class : RasterBrick
dimensions : 77, 101, 7777, 3 (nrow, ncol, ncell, nlayers)
resolution : 1, 1 (x, y)
extent : 0, 101, 0, 77 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=merc +datum=WGS84
data source : in memory
names : layer.1, layer.2, layer.3
min values : 0, 0, 0
max values : 255, 255, 255
Data:
raster1 <- brick(system.file("external/rlogo.grd", package="raster"))
raster2 <- brick(system.file("external/rlogo.grd", package="raster"))
raster3 <- brick(system.file("external/rlogo.grd", package="raster"))
rlist <- list(raster1, raster2, raster3)

Removing the third dimension in SpatialPointsDataFrame

I have a SpatialPoints object with 3 dimensions :
x <- c(1,1,1,2,2,2,3,3,3)
y <- c(1,2,3,1,2,3,1,2,3)
z <- c(1,3,5,2,1,2,1,2,3)
xyz <- cbind(x,y,z)
ss <- SpatialPoints(xyz)
dimensions(ss)
And a raster object:
rr <- raster(matrix(round(runif(49,0,10)),7,7), xmn=0, xmx=4, ymn=0, ymx=4, crs=NA, template=NULL)
I want to extract the raster values using the SpatialPoints object:
extract(rr,ss)
#Error in .xyValues(x, coordinates(y), ..., df = df) :
# xy should have 2 columns only.
#Found these dimensions: 9, 3
You can visualize the data if you want:
plot(rr)
plot(ss, add=T)
So the problem is that the extract function of the raster package require a 2 dimension SpatialPoints object. Mine (in my real data) in 3 dimensional. Is there a way to drop the 3rd dimension of my point shape? I've tried:
coordinates(ss) <- coordinates(ss)[,-3]
#Error in `coordinates<-`(`*tmp*`, value = c(1, 1, 1, 2, 2, 2, 3, 3, 3, :
# setting coordinates cannot be done on Spatial objects, where they have #already been set
I don't want to have to rebuild my shape from scratch.
Just overwrite the coords slot of the S4 object:
ss#coords <- ss#coords[, 1:2]
I don't know how your SpatialPoints object is created, but if you use rgdal::readOGR there is a pointDropZ argument (default FALSE)
#rcs answer is better, but this works as well:
ss <- SpatialPoints(coordinates(ss)[,-3])
and if you have a SpatialPointsDataFrame:
ss <- SpatialPointsDataFrame(coordinates(ss)[,-3], ss#data,proj4string=CRS(proj4string(ss)))

Resources