R: Isolating Maps for Viewing and Export - r

I'm attempting to view one map separately from a raster stack of maps each with unique titles. When I run the map function, all 5 maps included in the raster stack are displayed side by side (see below). I am only interested in viewing and exporting the last. How would you go about isolating this map? Below is an image of the outputs and a link to the plotting function I'm using.
https://github.com/azizka/sampbias/blob/master/R/map_bias.R
Raster Stack maps

With these data
library(terra)
f <- system.file("ex/elev.tif", package="terra")
s <- rast(c(f, f, f))
You can plot all three layers
plot(s)
Or a single layer (here the second)
plot(s, 2)
Or a subset
plot(s, 2:3)
Alternatively, you can first subset s like this to get the second layer
r <- s[[2]]
And then use
plot(r)
Or functions from other packages. The above is for SpatRaster objects from the terra package. But it works the same for the RasterStack objects from raster.

Related

Raster calculation in R

I have two files from these website:
https://sedac.ciesin.columbia.edu/data/set/gpw-v4-population-count-rev11/data-download
And a shapefile of China from these website
https://gadm.org/download_country_v3.html
I would like to compute the difference between the raster population layers, that I can show a map where each pixel represents the change in the population in China.
I used this code
library(raster)
library(sf)
library(tmap)
p_15 <- terra::rast("gpw-v4-population-count-rev11_2015_2pt5_min_tif/gpw_v4_population_count_rev11_2015_2pt5_min.tif")
p_20 <- terra::rast("gpw-v4-population-count-rev11_2020_2pt5_min_tif/gpw_v4_population_count_rev11_2020_2pt5_min.tif")
CHN <- sf::read_sf("gadm36_CHN_shp/gadm36_CHN_1.shp")
CHN <- sf::st_transform(CHN, crs="epsg:4490")|> terra::vect()
p_15<- terra::project(p_15,'EPSG:4490')
p_20 <- terra::project(p_20,'EPSG:4490')
p_15_crop <- terra::crop(p_15, CHN)
p_20_crop <- terra::crop(p_20, CHN)
p_15_mask <- mask(p_15_crop, CHN)
p_20_mask <- mask(p_2_crop, CHN)
The code above everything works fine.
Now I used overlay from the raster package to calculate the difference between the population layers to show the change in each pixel.
I gave these code
diff1520 <- overlay(p_15_mask, p_20_mask, fun=function(x,y){return(y-x)})
But I got the error message method not applicable??? What is wrong with the code?
By the way, I also used geodata package, but did not solve my problem
Simply subtracting the objects will work. But if you still want to apply a function to a SpatRaster, you can use terra::lapp, which is equivalent to raster::overlay. The main difference is that you have to combine the layers first.
library(terra)
p_mask <- c(p_15_mask, p_20_mask)
diff1520 <- lapp(p_mask, fun=function(x,y){return(y-x)})
It's probably because you created your masks with terra. So the masks are SpatRast objects and you tried to use the overlay() function from raster and that only works with raster objects.
You can do what you want with
diff1520 <- p_20_mask - p_15_mask
That's the basic terra way.

How to rasterize sf geometries tile by tile?

What I´m looking for is a way to rasterize (or fasterize) geometries within each tile of a certain extent step by step and join the parts of the rasterized geometries to entire raster objects.
## create sample data
# create a frame
library(sf)
ob = st_sf(st_sfc(st_polygon(list(rbind(c(0,0), c(0,9), c(6,9), c(6,0), c(0,0)))))
# create tiles
library(GSIF)
tl <- getSpatialTiles(as(ob, 'Spatial'), block.x=3, overlap.percent=2)
plot(tl)
# create sample polygons
g <- st_sfc(st_point(c(1,2)), st_point(c(5,6)), st_point(c(2,4)), st_point(c(3,3)), st_point(c(3,4)), st_point(c(4,5)))
g.b <- st_buffer(g,0.6)
p <- st_sf(value = ceiling(10*runif(6)),
geometry = st_sfc(g.b))
plot(p, add=TRUE)
Cropping the polygons (or parts of polygons) that are within each tile works fine , i guess. My actual goal is to process the data tile by tile. It looks like the following loop does this and also joins the parts of the polygons to entire polygons. Well, the output (cr) is the same as the input (p)... I thought that this step might be necessary in order to rasterize the resulting (parts of) polygons in the next step. i didn´t expect that the polygons would be joined. I was trying to build a loop based on the intermediate result, therefore following lines are add:
# crop polygons (or parts) for each tile
result <- p
for(i in 1:length(tl)) {cr <- rbind(result, st_crop(p, tl[i]))}
cr <- cr[-7,]
library(scales)
plot(st_geometry(cr), col=alpha("white", 0.5), add=TRUE)
However, I struggle rasterizing the (intermediate) results.
Try this:
myF <- function(i){return(st_crop(p, tl[i]))}
cr <- do.call(rbind, lapply(1:length(tl), myF))

Dealing with unordered XY points to create a polygon shapefile in R

I've inherited a geodatabase of polygons of lakes for which I am trying to create sampling grids on each lake. My current strategy is to export spatial data to CSV, use R to run a loop to create the grids on each lake, and then write to a new shapefile. However, here is my problem, when exporting to a CSV the WKT strings get messed up and put onto different lines. Okay, no problem, I moved on to exporting just the geometry to CSV so that I get X-Y values. When I simply plot the points they look perfect (using plot(y~x)), but the points are not in order. So, when I transform the data to a SpatialPolygon in the sp package in R using the following sequence:
XY-points -> Polygon -> Polygons -> SpatialPolygon
and then plot the SpatialPolygon I get this:
I know this is an artifact of incorrectly ordered points, because when I order the points by X and then by Y and run the same procedure here is what I get:
This is what the correct plotting is supposed to look like (X-Y data plotted with open circles):
Here is a short reproducible example of what I am trying to deal with:
library(sp)
# correct polygon
data <- data.frame(x=c(1:10, 10:1), y=c(5:1, 1:10, 10:6))
# plot(y~x, data=data)
correct.data.points <- rbind(data, data[1,]) # to close the ring for a polygon
correct.data.coords <- as.matrix(cbind(correct.data.points))
correct.data.poly <- Polygon(correct.data.coords, hole=F)
correct.data.poly <- Polygons(list(correct.data.poly), ID=0)
correct.data.poly.sp <- SpatialPolygons(list(correct.data.poly))
plot(correct.data.poly.sp)
# incorrect polygon
scr.data <- data[c(sample(1:20)),]
# plot(y~x, data=scr.data)
scr.data.points <- rbind(scr.data, scr.data[1,]) # to close the ring for a polygon
scr.data.coords <- as.matrix(cbind(scr.data.points))
scr.data.poly <- Polygon(scr.data.coords, hole=F)
scr.data.poly <- Polygons(list(scr.data.poly), ID=0)
scr.data.poly.sp <- SpatialPolygons(list(scr.data.poly))
plot(scr.data.poly.sp)
Any thoughts? Thanks for any help or insight anyone can provide. Also, for reference I am using QGIS 2.6.0 and the MMQGIS Python plugin to do the geometry exporting.

Merging 2 raster images into one plot using the `raster` package

I would like to add an enlarged portion of my map to the original map and have as the final product, one map that shows both the original map, and also the enlarged/zoomed portion. Using the meuse dataset as an example:
library(sp)
library(lattice)
data(meuse)
coordinates(meuse)=~x+y
gridded(meuse)<-TRUE
rasters.m<-list()
for (i in 1:12){
rasDF <- raster(meuse, layer=i)
rasters.m[[i]]<-rasDF
}
stack.sp<-stack(rasters.m)
plot(stack.sp) # gives a gridded view of the stacked rasters. But now I would like to zoom in..
zoom.ent<-zoom(stack.sp,1) # The zoomed in portion appears as a new window, with the boundaries of the zoomed area highlighted in red on the original map.
I am not sure if there is a command in the raster or rasterVIS packages that would allow one to add the zoomed in part of the raster onto the original map. I have tried the par function but that doesn't work. Any suggestions would be welcomed.
This is more or less the same question you asked here. For Raster* objects you have to use the shift function. The result can be combined with the +.trellis function of the latticeExtra package:
library(raster)
library(rasterVis)
f <- system.file("external/test.grd", package="raster")
r <- raster(f)
rZoom <- crop(r, extent(180000, 181000, 330000, 331500))
displaced <- shift(rZoom, x = -1200, y = 2000)
levelplot(r) + levelplot(displaced)

How to do the raster package identify all bands (layers) of a image?

i'm trying to use de raster package to read a multilayer (multiband) image (ENVI format [.hdr]) that have 160 values of refletance and 160 values of wavelength per pixel, but when i use the code that i developed, the program returns only 1 band and the refletance value associated.section1=raster("./x")
getValuesBlock(section1, row=1, nrows=1, col=1, ncol=1 )
Well, from the looks of it , it seems to me that you want to read a particular band of a raster file into the R environment ,
require("raster")
dir.file<-"dir/file.hdf"
#Reading the first band of the raster image
band1<-raster(dir.file,band=1)
Change the values of theband parameter of the raster() method to control the band id of your raster.
Hope this helps
To create a multi-layer Raster object, you should use the brick function if they layers are in one file, or the stack function if they are in multiple files.
library(raster)
# example file name
f <- system.file("external/rlogo.grd", package="raster")
b <- brick(f)
b
# a single cell value
b[1]

Resources