I am trying to mask a raster to a shapefile boundary, but I am getting an error. How can I correctly perform this mask?
The raw data can be found here, entitled "data_for_question.txt." It is formatted so that users can copy and paste (from the web app) the text directly into an R window and generate a data frame. Otherwise, if one doesn't want to generate the data, the output raster (example_raster.tif) and shapefile (field_boundary.shp) can both also be found in the same link.
Here is what I have tried:
#Import necessary libraries
library(pacman)
p_load(sf,
spatstat,
maptools,
tidyverse,
ggplot2,
gstat,
sp,
rgdal,
raster,
spdep)
#Read shapefile
shp <- st_read("field_boundary.shp")
#Generate data to run interpolation on and project it to the desired CRS
data_sp <- SpatialPointsDataFrame(coords,
data[, c("OM", "data2")],
proj4string = CRS('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'))
#Perform an IDW interpolation:
grd <- SpatialPixels(SpatialPoints(makegrid(data_sp, n=10000)), proj4string = proj4string(data_sp)) #Generate grid for interpolation
plot(grd)
interp <- idw(formula = OM ~ 1, data_sp, grd, idp = 0.5, nmax = 12)
plot(interp) #Makes for a very pretty picture!
#Convert to raster
rast <- raster(interp)
plot(rast)
shp <- st_transform(shp, crs(rast))
#Crop and mask the raster
crop_rast <- crop(rast, shp)
crop_om <- mask(crop_rast, mask = shp)
The error occurs here:
Error in h(simpleError(msg, call)) :
error in evaluating the argument 'x' in selecting a method for function 'addAttrToGeom': sp supports Z dimension only for POINT and MULTIPOINT.
use `st_zm(...)` to coerce to XY dimensions
I have a point shapefile ("search_effort.shp") that is highly clustered and an NDVI raster (resolution in m: 30.94948, 30.77829). I would like to subset my search_effort.shp by selecting 1 point per raster grid cell and create a new search_effort shapefile. I am using R version 4.0.3
I think I could have used Package ‘gridsample’ (in 'raster' v1.3-1), but it was removed from the CRAN repository and I would prefer not to use the archived version. Is there another way to do this in R?
I have also tried sample.grid but I do not know how to specify my raster as the grid, and have tried the following:
# NDVI raster to be used as the reference extent
NDVI_extent <-readGDAL('C:/Model_layers/NDVI.tif')
# Load the file names
layername <- "SearchEffort"
# Read in the shapefile
search_effort <- readOGR(dsn= ".", layer = layername)
plot(search_effort)
# Set the reference extent
r <- raster(NDVI_extent)
# Extract coordinates from the shapefile
search_effort#coords <- search_effort#coords[, 1:2]
#Subset points
sample.grid(search_effort, cell.size = c(30.94948, 30.77829), n = 1)
I get the following error:
"Error in validObject(.Object) : invalid class “GridTopology” object: cellsize has incorrect dimension."
I get the same error regardless of the cell.size I specify.
Example data
library(raster)
r <- raster(res=30)
values(r) <- 1:ncell(r)
x <- runif(1000,-180,180)
y <- runif(1000,-90,90)
xy <- cbind(x, y)
Solution
library(dismo)
s <- gridSample(xy, r, n=1)
Illustration
plot(as(r, "SpatialPolygons"))
points(s, col="red")
points(xy, cex=.1, col="blue")
I am trying to convert a SpatialPointsDataframe to a SpatialGridDataframe in order to use the slopeasp() function from the landsat package to get the values for slope. I tried to convert the SpatialPointsDataframe to a raster to convert it but it also didn't work and I get the error.
Error in as(pts, "spatialGridDataFrame") :
no method or default for coercing “SpatialPointsDataFrame” to “spatialGridDataFrame”
Here is my code below:
#create fake data
x <- rep(rep(seq(12,36,0.5),41))
y <-rep(seq(32,52,0.5), each=49)
z <- rnorm(2009, 26.5, 44.0)
pts <- as.data.frame(matrix(c(x,y,z), ncol=3, byrow=FALSE))
colnames(pts)=c("x", "y", "z")
# create a SpatialPointsDataFrame
coordinates(pts) = ~x+y
# create an empty raster object to the extent of the points
rast <- raster(ext=extent(pts), resolution=250)
# rasterize irregular points
rasOut<-rasterize(pts, rast, pts$z, fun = mean)
#attempt from spdf to sgdf
sgdf <- as(pts, 'spatialGridDataFrame')
#atempt from raster to sgdf
sgdf <- as(rasOut, 'spatialGridDataFrame')
Does anyone have any suggestions on how to get a spatialGridDataFrame? Thanks!
The as conversion to spatialGridDataFrame expects an object of class class SpatialPixelsDataFrame:
Objects from the Class
Objects can be created by calls of the form as(x,
"SpatialGridDataFrame"), where x is of class
SpatialPixelsDataFrame-class, or by importing through rgdal. Ordered
full grids are stored instead or unordered non-NA cells;
So, you can convert your pts to SpatialPixelsDataFrame, then convert the resulting SpatialPixelsDataFrame to SpatialGridDataFrame as you did.
#attempt from spdf to sgdf
sgdf <- as(pts, 'SpatialPixelsDataFrame')
# Convert the SpatialPixelsDataFrame (sgdf) to spatialGridDataFrame
sgdf <- as(sgdf, "SpatialGridDataFrame")
You can also convert your rasOut in the same fashion. In one line of code, this is:
#atempt from raster to sgdf
sgdf <- as(as(rasOut, 'SpatialPixelsDataFrame'), 'SpatialGridDataFrame')
I would like to sample a big raster by creating In small raster 100x100 cells.
I don't know how to do that so any ideas are welcome
My actual lead :
library(raster)
library(spatstat)
library(polyCub)
r <- raster(ncol=1000,nrow=1000) # create empty raster
r[] <- 1:(1000*1000) # Raster for testing
e <- extent(r) # get extend
# coerce to a SpatialPolygons object
p <- as(e, 'SpatialPolygons')
nc <- as.owin.SpatialPolygons(p) #polyCub
pts <- rpoint(50, win = nc)
plot(pts)
Now I need to generate 100x100 cell square around my 50 points and I would like to crop r using those square and stack each small raster individually ...
The answer by #adrian-baddeley basically has the ingredients to do what
you want. If you simply want a list of small im objects that contain
the 100x100 box you simply subset im objects by owin objects to
extract the relevant region. Here is an example (with fewer points to
avoid overplotting)
library(raster)
library(spatstat)
library(maptools)
r <- raster(ncol=1000,nrow=1000) # create empty raster
r[] <- 1:(1000*1000) # Raster for testing
e <- extent(r) # get extend
# coerce to a SpatialPolygons object
p <- as(e, 'SpatialPolygons')
nc <- as.owin.SpatialPolygons(p)
set.seed(42)
pts <- rpoint(7, win = nc)
rim <- as.im.RasterLayer(r)
Box <- owin(c(-50,50) * rim$xstep, c(-50,50) * rim$ystep)
The following is a list of im objects of size 100x100
imlist <- solapply(seq_len(npoints(pts)),
function(i) rim[shift(Box, pts[i])])
Here is a plot of the im objects in the region and the points on top
plot(pts)
for(i in imlist) plot(i, add = TRUE)
plot(pts, pch = 19, add = TRUE)
You can convert to a list of raster layers with
rasterList <- lapply(imlist, as, Class = "RasterLayer")
PS: The following is a list of im objects of the original size with
NA outside the 100x100 box if you need that format instead
imlist <- solapply(seq_len(npoints(pts)),
function(i) rim[shift(Box, pts[i]), drop = FALSE])
If you want to use spatstat then you need to convert the raster object r into an object of class im supported by spatstat. You can do this conversion in the maptools package. Call this image object rim. Then you can do as follows
Box <- owin(c(-50,50) * rim$xstep, c(-50,50) * rim$ystep)
BoxesUnion <- MinkowskiSum(pts, Box)
W <- intersect.owin(as.mask(rim), BoxesUnion)
This would give you the subset of the raster that is covered by the squares.
If you want to keep the squares separate, do something like
M <- as.mask(rim)
BoxList <- solapply(seq_len(npoints(pts)),
function(i) intersect.owin(M, shift(Box, pts[i])))
Then BoxList is a list of the individual sub-rasters.
My problem is simple. I have found very good package called adehabitat in R. To use it I need to transform my data into specificaly structured object containing raster map data and coordinates of an animal. To see it please type:
# example data in adahabitat package
data(bauges)
bauges
str(bauges)
How do I convert my data (bellow) into such structure? I figured out how to convert $locs into SpatialPoints, but I don't know how to convert map (in my example are raster values categorical codes of individual types of habitat -i.e. not continuous variable).
# My example data:
library(raster)
library(adehabitatHS)
# map
habitat_type_temp <- matrix(c(1,1,1,1,1,1,1,1,2,2,
1,1,2,2,1,1,1,2,2,2,
1,2,2,2,3,3,3,2,2,2,
2,2,2,1,1,1,3,2,2,1,
2,2,1,1,1,1,3,2,1,1,
2,1,1,1,1,1,3,3,1,1,
2,1,1,1,1,3,3,3,3,1,
1,1,1,1,1,1,1,3,3,3), 10)
habitat_type <- t(habitat_type_temp)
# coordinates
animal_coords <- data.frame(x = c(2,4,5,5,6,9),
y = c(2,8,3,2,4,3))
# see the situation
plot(raster(habitat_type, xmn=1, xmx=10, ymn=1, ymx=8))
points(animal_coords$x, animal_coords$y)
# creating object which could be manipulated in adehabitat package
my.hab <- list()
my.hab$map <- SpatialPixelsDataFrame(...)
my.hab$locs <- SpatialPoints(animal_coords)
Is it even possible to insert such manually fabricated data into such specific type of object, or I need some original tiff with specific CRS?
You could just drop the location somewhere to produce the SpatialPixelsDataFrame, I think this is roughly Iowa:
x <- 93+rep(1:8,each=10)/100
y <- rep(seq(42.01,42.1,by=0.01), 8)
z <- c(1,1,1,1,1,1,1,1,2,2,
1,1,2,2,1,1,1,2,2,2,
1,2,2,2,3,3,3,2,2,2,
2,2,2,1,1,1,3,2,2,1,
2,2,1,1,1,1,3,2,1,1,
2,1,1,1,1,1,3,3,1,1,
2,1,1,1,1,3,3,3,3,1,
1,1,1,1,1,1,1,3,3,3)
xy.df <- data.frame(x,y)
xy.coords <- SpatialPixels(SpatialPoints(xy.df))
llCRS <- CRS("+proj=utm +zone=15 +ellps=WGS84")
xy.sp <- SpatialPoints(xy.coords, proj4string = llCRS)
xyz <- as.data.frame(cbind(x,y,z))
xyz.spdf <- SpatialPixelsDataFrame(xy.coords, xyz)
plot(xyz.spdf)
Your spatialpoints would have to be changed similarly.