repeat same raster layer to create a raster stack - r

I am trying to create a raster stack from a rasterlayer, where the raster stack is just the same raster layer repeated a certain number of times.
I can do something like this:
library(raster)
rasterstack <- addLayer(rasterlayer, rasterLayer, rasterLayer)
and this works. However, i want the stack to be about a 1000 layers. I guess i could just loop through, but i was wondering if there was a more sophisticated way to doing this.
The reason I am trying to do this is to calculate the weighted mean of a raster stack with data where each layer is a different time period, and where the weights are in a different raster layer object. I am hoping that if I create a rasterstack from the weights raster layer with the same number of layers as the data, I'll be able to do something like:
weightedmean <- weighted.mean( data.RasterStack, weights.RasterStack )

Example data
library(raster)
r <- raster(ncol=10, nrow=10, vals=1:100)
Solution
n <- 10 # number of copies
s <- stack(lapply(1:n, function(i) r))
Or
s <- stack(replicate(n, r))

Related

Convert a column value(s) in SpatialpolygonDataframe into raster image

I need help with converting a variable or column values in a spatial polygon into a raster image. I have spatial data of administrative units with income(mean) information for each unit. I want to convert this information into raster for further analysis.
I tried the code below but it didn't work.
r <- raster(ncol=5,nrow=15)
r.inc <- rasterize(DK,r,field=DK#data[,2],fun=mean)
Where SP is the spatial polygon and the mean income for each spatial unit stored in column 2 of the SpatialPolygonDataframe. Can anyone help with a function or code of how to rasterise the values in the column of interest? An example of the spatialpolygondataframe (created) and my attempt to rasterize the data are below
suppressPackageStartupMessages(library(tidyverse))
url = "https://api.dataforsyningen.dk/landsdele?format=geojson"
geofile = tempfile()
download.file(url, geofile)
DK <- rgdal::readOGR(geofile)
DK#data = subset(DK#data, select = c(navn))
DK#data$inc = runif(11, min=5000, max=80000)
require(raster)
r <- raster(ncol=5,nrow=15)
r.inc <- rasterize(DK,r,field=DK#data[,2],fun=mean)
plot(r.inc)
Thank you.
Acknowledgement: The code for creating the sample SPDF was sourced from Mikkel Freltoft Krogsholm (link below).
https://www.linkedin.com/pulse/easy-maps-denmark-r-mikkel-freltoft-krogsholm/?trk=read_related_article-card_title
Here's something that makes a raster.
library(tidyverse)
library(rgdal)
library(raster)
url <- "https://api.dataforsyningen.dk/landsdele?format=geojson"
geofile <- tempfile()
download.file(url, geofile)
DK <- rgdal::readOGR(geofile)
r_dk <- raster(DK, nrows = 100, ncols = 100) # Make a raster of the same size as the spatial polygon with many cells
DK$inc <- runif(nrow(DK), min=5000, max=80000) # Add some fake income data
rr <- rasterize(DK, r_dk, field='inc') # Rasterize the polygon into the raster - fun = 'mean' won't make any difference
plot(rr)
The original raster was the size of the whole Earth so I think Denmark was being averaged to nothing. I resolved this by making an empty raster based on the extent of the DK spatial polygons with 100x100 cells. I also simplified the code. Generally, if you find yourself using # with spatial data manipulation, it's a sign that there might be a simpler way. Because the resolution of the raster is much larger than the size of each DK region, taking the average doesn't make much difference.

r - analogous sp method for raster::calc OR method for computing sp::over with sp and raster object

The core of my problem is that I want to minimize the number of times I need to convert an object between sp format (i.e. SpatialPixelsDataFrame) and Raster* format.
The task is the following: I start with a list of SPixDF (since this is the output of an external function I don't have control over) objects and I need to do two things with them.
I need to average them together into a single object. The solution needs to be generalizable (i.e. handle lists of varying length). Basically, I can't figure out a way to do raster::calc() with SPixDF objects.
The reason I need the solution for #1 is because the next step involves overlaying points on the resulting averaged SPixDF surface (i.e. sp::over). And sp::over() can't overlay SpatialPoints data on data in Raster* format.
## Data set-up ##
# grid data
data(meuse.grid)
coordinates(meuse.grid) = ~x+y
proj4string(meuse.grid) <- CRS("+init=epsg:28992")
gridded(meuse.grid) = TRUE
spplot(meuse.grid)
meuse.grid.list <- list(meuse.grid, meuse.grid, meuse.grid)
# point data
data(meuse)
coordinates(meuse) = ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")
### Analysis steps (involving 2 conversions) ###
# Convert listed SPixDF to listed RasterLayer
meuse.raster.list <- lapply(meuse.grid.list, function(x) raster(x, layer=5, values=T))
meuse.raster.stack <- stack(meuse.raster.list) # list of RasterLayers to RasterStack
# task #1
meuse.cmbnd <- calc(meuse.raster.stack, mean) # average together individual rasters
# Convert back to SPixDF
meuse.cmbnd.spdf <- as(meuse.cmbnd, "SpatialPixelsDataFrame")
# task #2
# overlay points on SPixDf grid
Result <- over(meuse, meuse.cmbnd.spdf)
If sp::over() could handle Raster* objects, then I would just convert the initial object once (to Raster*) and do steps 1 and 2 in that format. So essentially the problem is that I can't figure out a GENERALIZABLE way of conducting both steps in the same format (either sp or Raster).
If you think of anything I would be most grateful!
P.S. The background of this is that this operation is currently written in a function I'm working on, and I am trying to speed it up. But because I have to keep switching between sp and Raster classes, the solution I have becomes slower than the existing formulation.

Query raster brick layer based on another raster in R

I have a NetCDF file of global oceanographic (OmegaA) data at relatively coarse spatial resolution with 33 depth levels. I also have a global bathymetry raster at much finer resolution. My goal is to use get the seabed OmegaA data from the NetCDF file, using the bathymetry data to determine the desired depth. My code so far;
library(raster)
library(rgdal)
library(ncdf4)
# Aragonite data. Defaults to CRS WGS84
ncin <- nc_open("C:/..../GLODAPv2.2016b.OmegaA.nc")
ncin.depth <- ncvar_get(ncin, "Depth")# 33 depth levels
omegaA.brk <- brick("C:/.../GLODAPv2.2016b.OmegaA.nc")
omegaA.brk <-rotate(omegaA.bkr)# because netCDF is in Lon 0-360.
# depth raster. CRS WGS84
r<-raster("C:/....GEBCO.tif")
# resample the raster brick to the resolution that matches the bathymetry raster
omegaA.brk <-resample(omegaA.brk, r, method="bilinear")
# create blank final raster
omegaA.rast <- raster(ncol = r#ncols, nrow = r#nrows)
extent(omegaA.rast) <- extent(r)
omegaA.rast[] <- NA_real_
# create vector of indices of desired depth values
depth.values<-getValues(r)
depth.values.index<-which(!is.na(depth.values))
# loop to find appropriate raster brick layer, and extract the value at the desired index, and insert into blank raster
for (p in depth.values.index) {
dep.index <-which(abs(ncin.depth+depth.values[p]) == min(abs(ncin.depth+depth.values[p]))) ## this sometimes results in multiple levels being selected
brk.level <-omegaA.brk[[dep.index]] # can be more than on level if multiple layers selected above.
omegaA.rast[p] <-omegaA.brk[[1]][p] ## here I choose the first level if multiple levels have been selected above
print(paste(p, "of", length(depth.values.index))) # counter to look at progress.
}
The problem: The result is a raster with massive gaps (NAs) in it where there should be data. The gaps often take a distinctive shape - eg, follow a contour, or along a long straight line. I've pasted a cropped example.
enter image description here
I think this could be because either 1) for some reason the 'which' statement in the loop is not finding a match or 2) a misalignment of the projections is created which I've read can happen when using 'Rotate'.
I've tried to make sure all the extents, resolutions, number of cells, and CRS's are all the same, which they seem to be.
To speed up the process I've cropped the global brick and bathy raster to my area of interest, again checking that all the spatial resolutions, etc etc match - I've not included those steps here for simplicity.
At a loss. Any help welcome!
Without a reproducible example, this kind of problems is hard to solve. I can't tell where your problem is but I'll present to you the approach I would try. Maybe it's good, maybe it's bad, I don't know but it may inspire you to find a way to go around your problem.
To my understanding, you have a brick of OmegaA (33 layers/depth) and a bathymetry raster. You want to get the OmegaA value at the bottom of the sea. Here is how I would do:
Make OmegaA raster to the same resolution and extent to the bathymetry one
Transforme the bathymetry raster into a raster brick of 33 three layers of 0-1. e.g. If the sea bottom is at 200m for one particular pixel, than this pixel on all depth layer other than 200 is 0 and 1 for the 200. To program this, I would go the long way, something like
:
r_1 <- r
values(r_1) <- values(r)==10 # where 10 is the depth (it could be a range with < or >)
r_2 <- r
values(r_2) <- values(r)==20
...
r_33 <- r
values(r_33) <- values(r)==250
r_brick <- brick(r_1, r_2, ..., r_33)
then you multiple both your raster bricks. They have the same dimension, it should be easy. The output should be a raster brick of 33 layers with 0 everywhere where it isn't the bottom of the sea and the value of OmegaA anywhere else.
Combine all the layer of the brick obtained previously into a simple raster with a sum.
This should work. If you have problem with dealing with raster brick, you could make the data into base R arrays, it could be simpler.
Good luck.

R raster functions, splitting multiple rasters from one

I have a simple function splitting a raster object into three different classes. However my function doesn't return these rasters. I also read this tutorial http://cran.r-project.org/web/packages/raster/vignettes/functions.pdf
and according to it this is "a really bad way of doing this". However the 'right way' seems overly complicated. Is it really that there is no simple way of doing this (i.e., considering functions should make things easier for you not the vice versa).
I'm quite new to processing rasters with R so forgive me my stupid question..
rm(list=ls(all=T))
r <- raster(ncol=10, nrow=10)
r[] <- rnorm(100,100,5)
# Create split function // three classes
splitrast <- function(rast, quantile) {
print("Splitting raster...")
(q <- quantile(rast, probs=quantile))
r1 <- rast; r2 <- rast; r3 <- rast # copy raster three times
r1[rast > q[1]] <- NA #raster value less than .25 quantile
r2[rast <= q[1] | rast >= q[2]] <- NA #raster values is between quantiles
r3[rast < q[2]] <- NA #raster values is over .75 quantile
par(mfrow=c(1,3))
plot(r1);plot(r2);plot(r3)
rast <- brick(r1,r2,r3)
return(rast)
}
splitrast(r,c(0.2,0.8))
ls()
EDIT: reproducible example added
Don't try to return them separately. Instead return(list(r1,r2,r3)). But see comments about style.
The R raster subset function can help here. After you return the brick, you can subset each band as separate rasters.
# split the raster - returns a three band stack
rasters = splitrast(r,c(0.2,0.8))
# subset each band of the stack as a separate raster
r1 = subset(rasters, 1)
r2 = subset(rasters, 2)
r3 = subset(rasters, 3)
# proof - plot the separate rasters - same as those plotted in the function
plot(r1);plot(r2);plot(r3)

In R, how to average spatial points data over spatial grid squares

Managed to solve problem now
I have a set of around 50 thousand points that have coordinates and one value associated with them. I would like to be able to place points into a grid averaging the associated value of all points that fall into a grid square. So I want to end up with an object that identifies each grid square and gives the average inside the grid square.
I have the data in a spatial points data frame and a spatial grid object if that helps.
Improving answer: I have definitely done some searching, sorry about the initial state of the question I had only managed to frame the question inside my own head; hadn't had to communicate it to anyone else before...
Here is example data that hopefully illustrates the problem more clearly
##make some data
longi <- runif(100,0,10)
lati <- runif(100,0,10)
value <- runif(500,20,30)
##put in data frame then change to spatial data frame
df <- data.frame("lon"=longi,"lat"=lati,"val"=value)
coordinates(df) <- c("lon","lat")
proj4string(df) <- CRS("+proj=longlat")
##create a grid that bounds the data
grd <- GridTopology(cellcentre.offset=bbox(df)[,1],
cellsize=c(1,1),cells.dim=c(11,11))
sg <- SpatialGrid(grd)
Then I hope to get an object albeit a vector/data frame/list that gives me the average of value in each grid cell/square and some way of identifying which cell it is.
Solution
##convert the grid into a polygon##
polys <- as.SpatialPolygons.GridTopology(grd)
proj4string(polys) <- CRS("+proj=longlat")
##can now use the function over to select the correct points and average them
results <- rep(0, length(polys))
for(i in 1:length(polys)) {
results[i] = mean(df$val[which(!is.na(over(x=df,y=polys[i])))])
}
My question now is if this is the best way to do it or is there a more efficient way?
Your description is vague at best. Please try to ask more specific answers preferably, with code illustrating what you have already tried. Averaging a single value in your point data or a single raster cell makes absolutely no sense.
The best guess at an answer I can provide is to use raster extract() to assign the raster values to a sp point object and then use tapply() to aggregate the values to your grouping values in the points. You can use the coordinates of the points to identify cell location or alternately, the cellnumbers returned from extract (per below example).
require(raster)
require(sp)
# Create example data
r <- raster(ncol=500, nrow=500)
r[] <- runif(ncell(r))
pts <- sampleRandom(r, 100, sp=TRUE)
# Add a grouping value to points
pts#data <- data.frame(ID=rownames(pts#data), group=c( rep(1,25),rep(2,25),
rep(3,25),rep(4,25)) )
# Extract raster values and add to #data slot dataframe. Note, the "cells"
# attribute indicates the cell index in the raster.
pts#data <- data.frame(pts#data, extract(r, pts, cellnumbers=TRUE))
head(pts#data)
# Use tapply to cal group means
tapply(pts#data$layer, pts#data$group, FUN=mean)

Resources