Compile multiple raster extractions to one table - r

I have 3 rasters in which I have extracted data from using a polyline from a shapefile. Currently, I have the extraction as 3 separate lists. Is there A way I can do an extraction from all three rasters and compile them to one table with different columns for the data from each raster?
This is the current code I am using
Harney_Transects <- readOGR(dsn = ".", layer = "Transect_HN")
MeanTreeHeightHarneyBefore=raster('HN_TrMean_B_Clip.tif')
ScanAngleHarneyBefore= raster('HNScanAngle_B_Clip.tif')
MeanShrubHeightHarneyBefore= raster('HN_MeanShrub_B_Clip.tif')
Extraction_Shrub_Harney= extract(MeanShrubHeightHarneyBefore,Harney_Transects)
Extraction_Tree_Harney= extract(MeanTreeHeightHarneyBefore,Harney_Transects)
Extraction_ScanAngle_Harney= extract(ScanAngleHarneyBefore,Harney_Transects)

In short, you can stack() all the rasters you want to extract data from, and extract from the stack.
Here's a fully reproducible example using two rasters and a SpatialLines object, like you have in your question. Skip to the last code chunk for a direct answer to your question.
library(sp)
library(raster)
# function to generate random rasters
gen_raster <- function(){
r <- raster(nrows = 10, ncols = 10, res = 1,
xmn = 0, xmx = 10, ymn = 0, ymx = 10,
vals = rnorm(100, 5, 1))
return(r)
}
# generate 2 random rasters
r1 <- gen_raster()
r2 <- gen_raster()
# view
par(mfrow = c(1,2))
plot(r1, main = "raster 1"); plot(r2, main = "raster 2")
dev.off()
# generate transect (`SpatialLines` object)
m <- as.matrix(data.frame(x = 5.5, y = seq(0, 10, 1)))
l <- list(Lines(Line(m), "m"))
l <- SpatialLines(l)
# view the transect
plot(r1, main = "raster 1 with transect"); lines(l)
Running extract on the stacked rasters returns a list with a matrix in it. The last thing you'll want is to pull this out as a data.frame, which is a bit tricky.
rs <- stack(r1, r2) # stack any amount of rasters to extract from
re <- extract(rs, l) # extract at locations `l`
do.call(rbind.data.frame, re) # convert to data.frame
layer.1 layer.2
1 4.586890 5.115136
2 4.780503 5.093281
3 6.877302 3.337345
4 5.913230 3.755099
5 4.907834 4.887160
6 5.576908 5.386136
7 3.572350 5.225392
8 4.778727 5.391765
9 6.600041 4.205841
10 6.946321 5.544172
The names of the columns are the names of the raster layers in the stack. You can access these names with names(rs), and modify them with names(rs) <- c("new_name_1", "new_name_2").

Related

R function to convert polygon (sf, wkt) into mask (matrix, array)

I have an image stored as matrix with grayscale for each pixel.
On this image I use SLIC algorithm to divide it into areas.
So I get a simple feature (sf) with polygons, I am able to extract in well-known-text (wkt).
But what I really need is a matrix/mask (same dimension as my pixel-image-matrix) storing the id of the polygon each pixel belongs to. For example the pixel image[1,2] belongs to polygon 5, then mask[1,2] <- 5.
I add some code to give example of my porblem (for a random "image"):
mat <- array(runif(10000, min=0, max=500), dim=c(100,100))
# SLIC
library(supercells);
library(sf);
library(terra);
# make spatial raster from matrix
raster <- rast(mat);
rasterSLIC <- supercells(raster, k = 50, compactness = 1, dist_fun = "euclidean", avg_fun = "mean");
plot(raster);
plot(st_geometry(rasterSLIC), add = TRUE, lwd = 0.2);
point <- st_cast(rasterSLIC$geometry[2], to="POINT");
coord <- st_coordinates(point);
# what I want:
goal <- array(c(1,1,1,2,2,1,2,3,3), dim=c(3,3));
image(goal);
goal;
I would like to have something that helps me turning coords into such a mask/matrix I gave a small example for in goal.
You can use terra::rasterize
Example data
library(terra)
# polygons
f <- system.file("ex/lux.shp", package="terra")
v <- vect(f)
# arbitrary raster
r <- rast(v, res=.01)
Solution:
rid <- rasterize(v, r, 1:nrow(r))
#or
v$ID <- 1:nrow(v)
rid <- rasterize(v, r, "ID")
Illustration
plot(rid, type="classes")
text(v)
lines(v)
To get the a matrix of the raster values you can do
m <- as.matrix(rid, wide=TRUE)
With your more specific example, you could do
library(supercells);
library(terra)
set.seed(1)
mat <- array(runif(10000, min=0, max=500), dim=c(100,100))
r <- rast(mat)
SLIC <- supercells(r, k = 50, compactness = 1, dist_fun = "euclidean", avg_fun = "mean");
x <- rasterize(SLIC, r, "supercells")
xm <- as.matrix(x, wide=TRUE)
plot(x);
s <- vect(SLIC)
lines(s)

convert a Kmeans to a Raster Layer

I have a problem .
I have a tiff image and I have made a Kmeans on it, the resulting file is a large Kmeans and I need to transform it back to RasterLayer in order to load it into a GIS. Any solution?
Biomasaencina<-raster("C:/Users/34600/Documents/dehesa.tif")
bio <-stack(Biomasaencina)
v <- getValues(bio)
k <- which(!is.na(v))
v <- na.omit(v)
#Kmeans
kmncluster<-kmeans(v,
centers= 2,
iter.max= 10,
nstart=2,
algorithm="Lloyd",
trace = FALSE)
#Convert to raster
kmeans_raster1 <- raster(Biomasaencina)
kmeans_raster1 <- setValues(Biomasaencina,kmncluster$cluster)
Error in setValues(Biomasaencina, kmncluster$cluster):length(values) is not equal to ncell(x), or to 1
writeRaster(kmeans_raster,filename = "k_means_dehesas",
format("GTiff"),
overwrite=TRUE)

Extracting random points from a raster within a grid cell

I would like to get non-NA values extracted from random coordinates of a raster within each grid cell.
An example of a raster
library(raster)
r <- raster(ncol = 10, nrow = 10, xmx = -80, xmn = -150, ymn = 20, ymx = 60)
values(r) <- runif(ncell(r))
An example of a grid
grid <- raster(extent(r))
res(grid) <- 15
proj4string(grid)<- proj4string(r)
gridpolygon <- rasterToPolygons(grid)
plot(r)
plot(gridpolygon, add = T)
How can I extract a value with random coordinates for each raster portions inside each grid cells?
I am really new at this kind of stuff so any suggestions will be very welcome.
Thanks.
You didn't specify all the condition for sampling, so I'm going by some assumptions here.
One can sample a point per grid polygon and extract the value. Here's how you can do it in one go and hope for the best:
# pick random points per each grid cell and plot
set.seed(357)
pickpts <- sapply(gridpolygon#polygons, spsample, n = 1, type = "random")
sapply(pickpts, plot, add = TRUE)
# extract values of raster cells at specified points
sapply(pickpts, FUN = extract, x = r)
Or you can do it in a loop and sample until you get a non-NA value.
N <- length(gridpolygon#polygons)
result <- rep(NA, times = N)
for (i in 1:N) {
message(sprintf("Trying polygon %d", i))
pl <- gridpolygon#polygons[[i]]
candval <- result[i] # start with NA
# sample until you get a non-NA hit
while (is.na(candval)) {
pickpoint <- spsample(pl, n = 1, type = "random")
candval <- extract(x = r, y = pickpoint)
}
result[i] <- candval
}
result
[1] 0.4235214 0.6081435 0.9126583 0.1710365 0.7788590 0.9413206 0.8589753
[8] 0.0376722 0.9662231 0.1421353 0.0804440 0.1969363 0.1519467 0.1398272
[15] 0.4783207

Extraction of pixel values in lines to each number of pixels

In my example I create a raster:
require(raster); require(sp)
## Raster Raster creation
r <- raster(nc=10, nr=10)
r <- setValues(r, round(runif(ncell(r))* 255))
After, I make pixels values extraction by selection of coordinates:
x <- c(-150)
y <- c(-80)
p <- data.frame(x,y)
pontos <- SpatialPoints(p)
p$cel <- cellFromXY(r, pontos)
p$col <- colFromCell(r, p$cel)
p$row <- rowFromCell(r, p$cel)
p
plot(r)
text(r)
points(pontos, pch = 4, col = 2)
But, I'd like to find a way to extract the value of the pixels in which I would select a coordinate and the function would perform the extraction of the pixels of entire horizontal lines of the raster to every two pixels from the given coordinate. For example, I choose xy(-150,-80) coordinates but my function below returns values only for the first line and need lines 4, 7 and 10 too.
require(plyr)
vals2cols <- ldply(1:nrow(p),
function(ir){
getValuesBlock(r,
col = p$col[ir],
ncols = 10,
row = p$row[ir],
nrows = 1)
}# end fun
)
df <- data.frame(p, vals2cols)
df
This is possible?

can raster create multi-layer objects with different modes?

Can a raster object (in R) have layers of different mode (data type)?
On the face of it it seems we are always forced to one type:
library(raster)
## create a SpatialPixelsDataFrame with (trivially) two different "layer" types
d <- data.frame(expand.grid(x = 1:10, y = 2:11), z = 1:100, a = sample(letters, 100, replace = TRUE), stringsAsFactors = FALSE)
coordinates(d) <- 1:2
gridded(d) <- TRUE
## now coerce this to a raster brick or stack and our "a" is crushed to numeric NA
all(is.na(getValues(brick(d)[[2]])))
[1] TRUE
Is there anything like a rasterDataFrame?
Also, note that we presumably cannot use R's factors since the raster#data is a matrix, or otherwise coerced to numeric/integer. Am I missing something?
The raster package provides the ability to create rasters with a categorical variable, and the rasterVis package includes functions for plotting them. The ratify function allows a raster to include a lookup table relating the underlying raster integer values to other values, which can be character. This directly allows the use of any other mode of value in the levels part of the ratified raster.
Here's an example.
library(rasterVis)
r <- raster(xmn = 0, xmx = 1, ymn = 0, ymx = 2, nrow = 10, ncol = 11,
crs = as.character(NA))
r[] <- sample(seq_along(letters[1:5]), ncell(r), replace = TRUE)
## ratify the raster, and set up the lookup table
r <- ratify(r)
rat <- levels(r)[[1]]
rat$value <- letters[1:5]
rat$code <- 1:5
## workaround for limitation as at 2013-05-01
## see https://stat.ethz.ch/pipermail/r-sig-geo/2013-May/018180.html
rat$code <- NULL
levels(r) <- rat
levelplot(r)
There are coming updates to rasterVis that make the workaround above unnecessary.

Resources