Convert GIS shape file to raster in R? - r

I need to convert shapefiles into raster format.
I used the function "rasterize" in R package "raster", but the result does not look correct.
tst <- rasterize(shpfile, r, fun="count")
Found 5 region(s) and 5 polygon(s)
There is no gird with occurrence records:
range(tst[],na.rm=TRUE)
[1] Inf -Inf
Warning messages:
1: In min(x) : no non-missing arguments to min; returning Inf
2: In max(x) : no non-missing arguments to max; returning -Inf
sum(tst[],na.rm=TRUE)
[1] 0
The R script that I wrote:
# download the GIS shape file
download.file("http://esp.cr.usgs.gov/data/little/abiebrac.zip",
destfile = "abiebrac.zip")
# unzip
unzip("abiebrac.zip")
# Read shapefile into R
library(maptools)
shpfile <- readShapePoly("abiebrac")
extent(shpfile)
# mapping
plot(shpfile)
library(maps)
map("world",xlim=c(-180,-50),ylim=c(7,83),add=FALSE)
plot(shpfile,add=TRUE,lwd=10)
# rasterize
library(raster)
GridSize <- 0.5 # degree
r <- raster(ncol= round(abs(-180-(-50))/GridSize),
nrow=round(abs(83-7)/GridSize))
extent(r) <- extent(c(-180, -50, 7, 83))
tst <- rasterize(shpfile, r, fun="count")
# summary
sum(tst[],na.rm=TRUE)
range(tst[],na.rm=TRUE)
# mapping
plot(tst,col="red",main="abiebrac")
map("world",xlim=c(-180,-50),ylim=c(7,83),add=TRUE)

I am not sure why you are using "count" in the fun argument but in this case, because there is no overlap, it is producing NA results. You also need to define an attribute field in the spatialPolygonDataFrame object to assign values to your raster. You can also pull the extent directly from the sp object.
This code seems to yield what you want.
require(raster)
require(rgdal)
require(sp)
setwd("D:/TMP")
shpfile <- readOGR(getwd(), "abiebrac")
r <- raster(extent(shpfile))
res(r)=0.05
r <- rasterize(shpfile, field="ABIEBRAC_", r)
plot(r)
plot(shpfile,lwd=10,add=TRUE)

Related

How to select one point per raster grid cell?

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")

R 'automap' how to create prediction grid to use with AutoKrige (e.g. meuse.grid)?

I'm having a lot of difficulty creating a prediction grid (for the new_data argument) to use with the autoKrige function in the automap package.
I've already tried following the steps in this post (How to subset SpatialGrid using SpatialPolygon) but get the following error :
Error in x#coords[i, , drop = FALSE] :
(subscript) logical subscript too long
In addition: Warning messages:
1: In min(x) : no non-missing arguments to min; returning Inf
2: In max(x) : no non-missing arguments to max; returning -Inf
My (limited) understanding is the error relates to there being no non-missing arguments because it is an empty grid. This is fine - all I want is an empty grid constrained by a polygon from a shapefile.
Here is the code I'm working with:
shp <- shapefile("C://path/path/Tobay_Box2.shp")
shp <- spTransform (shp,"+proj=utm +ellps=WGS84 +datum=WGS84")
grid <- GridTopology(cellcentre.offset=c(731888.0,7457552.0),cellsize=c(2,2),cells.dim=c(122,106))
grid <- SpatialPixelsDataFrame(grid,
data=data.frame(id=1:prod(122,106)),
proj4string=CRS("+proj=utm +ellps=WGS84 + datum=WGS84"))
plot(grid)
[see dropbox folder 'Grid.png']
bound <- shp#polygons
bound <- SpatialPolygons(bound, proj4string=CRS("+proj=utm +ellps=WGS84 +datum=WGS84"))
plot(bound)
[see dropbox folder 'Boundary plot.png']
clip_grid <- grid[!is.na(over(grid, bound)),]
No errors or warnings up to this point. But then...
plot(clip_grid)
Error in x#coords[i, , drop = FALSE] :
(subscript) logical subscript too long
In addition: Warning messages:
1: In min(x) : no non-missing arguments to min; returning Inf
2: In max(x) : no non-missing arguments to max; returning -Inf
or attempting to pass the object clip_grid through autokrige for the new_data argument:
PerInkrg <- autoKrige (PerArIn~1, hs1, clip_grid)
Error in predict.gstat(g, newdata = newdata, block = block, nsim = nsim, :
value not allowed for: %s %s newdata empty or only NA's
I've had no issues using the non-clipped grid (object = grid).
In a nutshell, I require this [see dropbox folder 'Autokrig plot'] but with the interpolated surfaced constrained (clipped) to the boundary extent of 'Torbay_Box2.shp'
P.S. I attempted to insert images of my plots and links to other posts I've used before asking for help here and a link to my data but as a new user I don't have enough reputation to do this - sorry!
Data and plots can be found on Dropbox.com/sh/yqg20z1ibl3h4aa/AACJnHoEuP-S5fTvAXxsnY1za?dl=0
I've now managed to produce an autoKrige [plot] which is masked to the extent of the Torbay_Box2 boundary. However, I never achieved this in the 'conventional' way by creating a prediction grid like meuse.grid. The result is the same so for now I'm happy but I would still like to do it the conventional way eventually.
Here's how I cheated it:
# Load sample box extent
bx.data <- readOGR (".", "Tobay_Box2")
bx <- spTransform(bx.data,"+proj=utm +ellps=WGS84 +datum=WGS84") #transformsto UTM projection
str(bx)
# Set the boundary extent with that of sample box extent
hs1#bbox <- bx#bbox
#create an empty grid
grd <- as.data.frame(spsample(hs1, "regular", n=50000))
names(grd) <- c("X", "Y")
coordinates(grd) <- c("X", "Y")
gridded(grd) <- TRUE # Create SpatialPixel object
fullgrid(grd) <- TRUE # Create SpatialGrid object
plot(hs1)
plot(grd, pch = ".", add = T)
proj4string(grd) <- proj4string(hs1)
I then performed an IDW interpolation using the empty grid as the newdata, converted the output to raster, clipped this to the Torbay_Box2 boundary and then converted this to a SpatialPixelDataFrame which I passed through as the new_data argument for autoKrige:
# For PerArIn (% area inhabited)
#interpolate the grid cells using all points and a power value of 2
hs1.idw <- gstat::idw(PerArIn ~ 1, hs1, newdata=grd, idp=2.0)
# Convert to raster object then clip to Hollicombe sample box
r <- raster(hs1.idw)
r.m <- mask(r, bx)
#Convert and set as prediction grid for Kriging
grd<- rasterToPoints(r.m, spatial=TRUE)
gridded(grd) <- TRUE
grd <- as (grd, "SpatialPixels")
#en voila!
PerInkrg <- autoKrige (PerArIn~1, hs1,grd)

Function to return values (velox raster)

I'm using the new velox extract function to speed up raster extraction by shapefiles.
The old raster package's extract function by default returned a list of cell values, for example when you use the below format:
val.list <- raster::extract(raster, shapefile)
The new velox package requires a fun= argument and I can't for the life of me get it to return the values:
vx.raster <- velox(raster)
vx.vals <- vx.raster$extract(shapefile, fun=??????)
I have tried:
fun=values (returns error Error during wrapup: unable to find an inherited method for function 'values' for signature 'numeric'
fun=function(x){values(x)} (same error as above)
I get fun=sum, fun=mean to work just fine. Whats up with values? Am I just missing something obvious about a numeric vector and returning a values list (which I feel is the most likely case)?
Thank you!
The development version of velox (on github) now allows returning 'raw' raster values from a VeloxRaster_extract query. Just set the fun argument to NULL.
Here's an example:
library(devtools)
install_github('hunzikp/velox')
library(velox)
## Make VeloxRaster with two bands
set.seed(0)
mat1 <- matrix(rnorm(100), 10, 10)
mat2 <- matrix(rnorm(100), 10, 10)
vx <- velox(list(mat1, mat2), extent=c(0,1,0,1), res=c(0.1,0.1),
crs="+proj=longlat +datum=WGS84 +no_defs")
## Make SpatialPolygons
library(sp)
library(rgeos)
coord <- cbind(0.5, 0.5)
spoint <- SpatialPoints(coords=coord)
spols <- gBuffer(spgeom=spoint, width=0.5)
## Extract
vx$extract(sp=spols, fun=NULL)$buffer
# [,1] [,2]
# [1,] 1.27242932 0.04658030
# [2,] 0.41464143 -1.13038578
# [3,] -1.53995004 0.57671878
# etc....
Simply try this snippet
vx.raster$crop(shapefile).

Plot raster time series (rts) object with Levelplot R after coercing to raster object

I would like to display the results in a raster times series object (rts) using levelplot function in rasterVis.
Here is a short code frome rts package:
library(raster)
library(rasterVis)
library(rts)
path <- system.file("external", package="rts")
lst <- list.files(path=path,pattern='.asc$',full.names=TRUE)
r <- stack(lst)
d <- c("2000-02-01","2000-03-01","2000-04-01","2000-05-01") # corresponding dates to 4 rasters
d <- as.Date(d)
# creating a RasterStackTS object:
rt <- rts(r,d)
To coerce from .rts to raster I used:
r=rt#raster
proj=CRS("+proj=longlat +datum=NAD27 +no_defs +ellps=clrk66 +nadgrids=#conus,#alaska,#ntv2_0.gsb,#ntv1_can.dat")
proj4string(r) <- proj
wgs84.p4s <- CRS("+proj=longlat +datum=NAD83 +ellps=GRS80 +no_defs")
reprojecting r from UTM coordinates to latlong coordinates
rx <- projectRaster(from=r, crs=wgs84.p4s#projargs, method="ngb")
writeRaster(rt, file="myfile100.tif", format="GTiff", overwrite=TRUE)
ras = raster("myfile100.tif")
How can I read all 4 layers in myfile100.tif?
ras = raster("myfile100.tif") reads only layer 1
proj4string(ras) <- proj
plot(ras)
levelplot(ras)
I get this error:
Error in projectExtent(from, projto) : cannot do this transformation
In addition: Warning message:
In rgdal::rawTransform(projfrom, projto, nrow(xy), xy[, 1], xy[, :
146 projected point(s) not finite
How can I get around this?
Maybe there is even a shorter and reasonable way to do this.
Thanks for your suggestions.

How to create a raster brick with rasters of different extents?

I am new in R so this question is very basic but I have been struggling with it and could not find a solution that worked. I want to create a raster brick from some landsat images of the same area.
They were downloaded in HDF-EOS format, and I used the Modis Reprojection Tool to convert them to .tif.
The resulting rasters have the same projection, but differ in their extent, resolution and origin.
I tried several approaches, summarized here below:
defining a subset extent manually and subsetting all the rasters. Then trying to make a brick with the subset rasters
Resampling the rasters, to give them the same number of columns and rows. Ideally that would ensure the raster cells are aligned and can be put into a raster brick. This option created a brick where rasters had no values, they were empty.
I am wondering what is the concept I should follow to correct the extent. Would it be correct (and efficient) to create an empty raster that I would fill in later with the values of the imported landsat image? Can you see where I am making a mistake?
In case it is relevant, I am working on a Mac OSX Version 10.9.1, and using rgdal version 0.8-14
Any help will be very appreciated!
Thankyou
I add here the code I have been using:
# .tif files have been creating using the Modis Reprojection Tool. Input
# files used for this Tool was LANDSAT HDF-EOS imagery.
library(raster)
library(rgdal)
setwd()=getwd()
# Download the files from dropbox:
dl_from_dropbox <- function(x, key) {
require(RCurl)
bin <- getBinaryURL(paste0("https://dl.dropboxusercontent.com/s/", key, "/", x),
ssl.verifypeer = FALSE)
con <- file(x, open = "wb")
writeBin(bin, con)
close(con)
message(noquote(paste(x, "read into", getwd())))
}
dl_from_dropbox("lndsr.LT52210611985245CUB00-vi.NDVI.tif", "qb1bap9rghwivwy")
dl_from_dropbox("lndsr.LT52210611985309CUB00-vi.NDVI.tif", "sbhcffotirwnnc6")
dl_from_dropbox("lndsr.LT52210611987283CUB00-vi.NDVI.tif", "2zrkoo00ngigfzm")
# Create three rasters
tif1 <- "lndsr.LT52210611985245CUB00-vi.NDVI.tif"
tif2 <- "lndsr.LT52210611985309CUB00-vi.NDVI.tif"
tif3 <- "lndsr.LT52210611987283CUB00-vi.NDVI.tif"
r1 <- raster(tif1, values=TRUE)
r2 <- raster(tif2, band=1, values=TRUE)
r3 <- raster(tif3, band=1, values=TRUE)
### Display their properties
# projection is identical for the three rasters
projection(r1)
# "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
projection(r2)
projection(r3)
# Extents are different
extent(r1)
# class : Extent
# xmin : -45.85728
# xmax : -43.76855
# ymin : -2.388705
# ymax : -0.5181549
extent(r2)
# class : Extent
# xmin : -45.87077
# xmax : -43.78204
# ymin : -2.388727
# ymax : -0.5208711
extent(r3)
# class : Extent
# xmin : -45.81952
# xmax : -43.7173
# ymin : -2.405129
# ymax : -0.5154312
# origin differs for all
origin(r1)
# 5.644590e-05 -8.588605e-05
origin(r2)
# 0.0001122091 -0.0001045107
origin(r3)
# 6.949976e-05 -5.895945e-05
# resolution differs for r2
res(r1)
# 0.0002696872 0.0002696872
res(r2)
# 0.0002696875 0.0002696875
res(r3)
# 0.0002696872 0.0002696872
## Try different approaches to create a raster brick
# a- define a subset extent, and subset all the rasters
plot(r1, main="layer1 NDVI")
de <- drawExtent(show=TRUE, col="red")
de
# class : Extent
# xmin : -45.36159
# xmax : -45.30108
# ymin : -2.002435
# ymax : -1.949501
e <- extent(-45.36159,-45.30108,-2.002435,-1.949501)
# Crop each raster with this extent
r1c <- crop(r1,e)
r2c <- crop(r2,e)
r3c <- crop(r3,e)
# Make raster brick
rb_a <- brick(r1c,r2c,r3c)
# Error in compareRaster(x) : different extent
# b- Resample each raster
s <- raster(nrow=6926, ncol=7735) # smallest nrow and ncol among r1,r2 and r3
r1_res <- resample(r1,s, method="ngb")
r2_res <- resample(r2,s, method="ngb")
r3_res <- resample(r3,s, method="ngb")
# Resampling gives for the three rasters the following message:
# Warning message:
# In .local(x, y, ...) :
# you are resampling y a raster with a much larger cell size,
# perhaps you should use "aggregate" first
# Make raster brick
rb_c <- brick(r1, r2, r3)
# Error in compareRaster(x) : different extent
here are some things to help you out. Since I don't have your .tif files just some hints. Have you checked the extent on your raster s? It's the size of the world, with just those columns its cells are extremely large. So you have to add an extent to your raster before resampling it. From your info I did something like this:
# create an extent that includes all your data
e<-extent(-46, -43, -2, -0.6)
# create a raster with that extent, and the number of rows and colums to achive a
# similar resolution as you had before, you might have to do some math here....
# as crs, use the same crs as in your rasters before, from the crs slot
s<-raster(e, nrows=7000, ncols=7800, crs=r1#crs)
# use this raster to reproject your original raster (since your using the same crs,
# resample should work fine
r1<-resample(r1, s, method="ngb")
Happy Holidays,
Ben
PS a better way to find your desired extent & resolution:
# dummy extent from your rasters, instead use lapply(raster list, extent)
a<-extent(-45.85728, -43.76855, -2.388705, -0.5181549)
b<-extent(-45.87077, -43.78204, -2.388727, -0.5208711)
c<-extent(-45.81952 ,-43.7173 , -2.405129 ,-0.5154312)
extent_list<-list(a, b, c)
# make a matrix out of it, each column represents a raster, rows the values
extent_list<-lapply(extent_list, as.matrix)
matrix_extent<-matrix(unlist(extent_list), ncol=length(extent_list)
rownames(matrix_extent)<-c("xmin", "ymin", "xmax", "ymax")
# create an extent with the extrem values of your extent
best_extent<-extent(min(matrix_extent[1,]), max(matrix_extent[3,]),
min(matrix_extent[2,]), max(matrix_extent[4,]))
# the range of your extent in degrees
ranges<-apply(as.matrix(best_extent), 1, diff)
# the resolution of your raster (pick one) or add a desired resolution
reso<-res(r1)
# deviding the range by your desired resolution gives you the number of rows and columns
nrow_ncol<-ranges/reso
# create your raster with the following
s<-raster(best_extent, nrows=nrow_ncol[2], ncols=nrow_ncol[1], crs=r1#crs)

Resources