R: Handling of sf objects in raster package - r

Previously I was using raster::crop and raster::mask with shapefiles of class Spatial*, read in using rgal::readOGR.
I am just "upgrading" my scripts to use sf for reading and manipulating polygons.
raster::crop
raster::crop expects an 'extent' object as second argument. Up to now, this was automatically extracted from a Spatial* object. So I could just do raster::crop(raster, polygon).
To get this working with an sf object, I can call raster::crop(raster, as.vector(st_bbox(polygon))) as an ugly workaround.
raster::mask
Since raster::mask clearly expects a Raster* object or a Spatial* object the only solution was to coerce the sf object back to a Spatial* object using as("Spatial").
I assume this problem generalized to all raster functions? Did I overlook something or is it just the case that the raster package does not (yet) work with sf objects?

For future reference, it works now! Here's some slightly modified example code from ?crop, tested with raster version 2.6-7 which has been released on 2017-11-13.
library(raster)
library(sf)
r <- raster(nrow=45, ncol=90)
r[] <- 1:ncell(r)
# crop Raster* with sf object
b <- as(extent(0, 8, 42, 50), 'SpatialPolygons')
crs(b) <- crs(r)
b <- st_as_sf(b) # convert polygons to 'sf' object
rb <- crop(r, b)
# mask Raster* with sf object
mb <- mask(r, b)

Related

Failing to assign projection to sp object SpatialPointsDataFrame

I have a SpatialPointsDataFrame called johnny, created from a vanilla dataframe by assigning coordinates. These coordinates are in coordinate system EPSG 4326 (the standard GPS geographic coordinate system), but johnny does not know that. So ,I am trying to assign EPSG 4326 to johnny, essentially as in this earlier question data projection in R using package SP . I, too, am using sp. My ultimate goal is to project johnny to projected_johnny. However, I can't seem to assign the existing projection correctly first. Who sees my mistake?
library(sp)
x <- seq(80,90,by=1)
y <- seq(40,50,by=1)
value <- seq(10,20,by=1)
johnny <- data.frame(cbind(x,y,value))
coordinates(johnny) <- ~x+y
class(johnny)
[1] "SpatialPointsDataFrame"
attr(,"package")
[1] "sp"
proj4string(johnny) <- CRS("+init=epsg:4326")
Error in if (is.na(get("has_proj_def.dat", envir = .RGDAL_CACHE))) { :
argument is of length zero
I have considered and rejected the following possible solutions after trying them out:
Adding library rdgal directly
using CRS("+proj=longlat +datum=WGS84") instead of CRS("+init=epsg:4326")
I am using R 3.6.0 and sp 1.3-1. The rgdal version loaded via sp is 1.5-15. Any ideas are welcome. This should be such a simple action...
I looked over your code and guessed what you are probably trying to accomplish. But the way you are going about things is more different than it needs to be. There is a simple way to accomplished this. By far, the easiest way to accomplish this is by using those tools found in the R, sf package. Know that the sf package is a newer package than the sp package. And the sf package provides easy to use tools for accomplishing these tasks.
The code below is somewhat different from your code. A two column matrix was used instead of your three column data frame.
The simple feature geometry points were created from the matrix. Then the simple feature column object was created from the geometry points. Then the plot was created.
Code:
# Create matrix
x <- seq(80,90,by=1)
y <- seq(40,50,by=1)
# value <- seq(10,20,by=1)
#johnny <- data.frame(cbind(x,y))
jm <- matrix(data = c(x,y), nrow = 11, ncol = 2)
# coordinates(johnny) <- ~x+y
# class(johnny)
# johnny
Create sf multipoint geometry:
jm.sfg <- st_multipoint(jm)
jm.sfg
Create sf column object:
jm.sfc <- st_sfc(jm.sfg, crs = 4326)
jm.sfc
Plot
plot(jm.sfc, axes = TRUE)
The plot can be viewed from link below.

vector shp point to ppp spatstat with polygon windows

I always get error to this
# polygon that to be window
neighborhoods <- st_read("neighborhoods/neighborhoods.shp")
# convert CRS to planar projection as recommended by (https://stackoverflow.com/questions/59597078/use-sf-polygon-object-as-window-in-spatstat)
neighborhoods_3857 <- st_transform(neighborhoods, crs = 3857)
# point that to be PPP spatstat
trees <- st_read("trees/trees.shp")
# convert to planar projection
trees_3857 <- st_transform(trees, crs = 3857)
The problems, the "trees_3857" doesn't have dataframe columns that represent in EPSG3857 coordinates, so Feature column of "trees_3857" doesn't have x and y columns that respect to EPSG 3857
q <- ppp(x=?, y=?, win=neighborhoods_3857)
what I have done but error
z <- as.ppp(trees_3857, win=neighborhoods_3857)
Error in as.ppp.sf(trees_3857, win = neighborhoods_3857): unused argument (win = neighborhoods_3857)
Traceback:
You can get the data freely from datacamp.
https://assets.datacamp.com/production/repositories/738/datasets/96a72364e69d872645038b3a6dc7c0dbcb1114d6/neighborhoods.zip
https://assets.datacamp.com/production/repositories/738/datasets/08a3684dc4d538d59ba051a64a834166883ab5d1/trees.zip
Although you're wanting to transform your data into an object of class "ppp" from the spatstat package, the error message indicates that the problem originated in the function as.ppp.sf which is part of the sf package.
The error message says unused argument: win which means that the function did not recognise or accept the argument win.
Just to make it more challenging, the function as.ppp.sf is not documented and is not visible... By typing sf:::as.ppp.sf we can see the function body and figure out that the function has only one argument, so it does not accept any window information.
This is not the way the generic function as.ppp is designed to work in the spatstat package, so if you looked for help(as.ppp) in spatstat, it's not surprising that you got confused.
The best solution is (as Ege Rubak suggests) to convert the point coordinates and then add the window information:
z <- as.ppp(trees_3857)
Window(z) <- as.owin(neighborhoods_3857)
The conversions as.ppp and as.owin will be executed using code in sf so I can't guarantee they will work. The assignment Window(z) <- will be executed in spatstat code, see help("Window<-.ppp").

Rasterizing Spdep's localG output

I'm reasonably new to R and I am trying to rasterize the output of spdep's localG function.
This code:
neigh2<-dnearneigh(profcurvPts, 0, 2)
list<-nb2listw(neigh2)
gistar<-localG(profcurvPts$layer, list)
girast<-rasterize(gistar, profcurv)
Yields an error unable to find an inherited method for function 'rasterize' for signature '"localG", "RasterLayer"'
I have tried changing the localG class to a data.frame, but it creates a 1 column matrix that still won't rasterize.
To sum it up: what should I do to get a raster of the localG output?
Thanks in advance!
You are trying to call an object of class localG which has no associated method for sp or raster classes. Here is a workflow for rasterizing a local G result.
First, add packages and data. The meuse object is of SpatialPointsDataFrame and meuse.grid starts as SpatialGridDataFrame but is coerced into a rasterLayer object for rasterizing the point data.
library(spdep)
library(raster)
data(meuse)
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")
data(meuse.grid)
coordinates(meuse.grid) = ~x+y
proj4string(meuse.grid) <- CRS("+init=epsg:28992")
gridded(meuse.grid) = TRUE
meuse.grid <- raster(meuse.grid)
Here we conduct the local G analysis.
nb <- dnearneigh(coordinates(meuse), 0, 500)
G <- localG(meuse$cadmium, nb2listw(nb, style="B"))
This is where we can coerce the localG results, join them to the point data and rasterize the results. You can use as.numeric for coercing from a localG object (basically a list object). Please read the help for raster::rasterize. The x argument requires SpatialPoints or a matrix of coordinates, y is a rasterLayer object to provide the raster dimensions and field represents the attribute that is being rasterized. If you need a background value for the raster that is other than NA then use the background argument.
meuse$G <- as.numeric(G)
spplot(meuse, "G")
Gr <- rasterize(coordinates(meuse), meuse.grid, field = meuse$G, background = NA)

Convert raster to im object

I would like to convert a raster to an im object but have so far been unable to do so.
Here is a reproducible example:
Create raster layer and add data to it:
r.toy <- raster(ncol=40, nrow=20)
r.toy[] <- rnorm(n=ncell(r.toy))
Plot the raster:
plot(r.toy)
Convert to image:
r.toy.im <- as.im(r.toy)
I receive the following error:
Error in as.im.default(r.toy) : Can't convert X to a pixel image
You just need to load the maptools package which can convert many spatial
formats in R:
library(raster)
library(spatstat)
library(maptools)
r.toy <- raster(ncol=40, nrow=20)
r.toy[] <- rnorm(n=ncell(r.toy))
r.toy.im <- as.im(r.toy)
plot(r.toy.im)
Created on 2018-11-11 by the reprex package (v0.2.1)

plot3d for readGDAL?

I would like to prepare 3D graph in R! using raster data.
I heard about command plot3d in raster package.
Unfortunately I have data in GeoTiff format, so it is impossible to read it directly through raster package (instead of it, to load this file, I am using readGDAL command).
Is there any opportunity to prepare 3D graph using such data?
How I can retrieve coordinates? I know how to get values of raster using as.matrix command, but because it is in GeoTiff format, I am unable to use xmin or xmax.
I do not see why you cannot read a geotiff with raster, but at any rate the SpatialGridDataFrame (package sp) provided by readGDAL (package rgdal) can be passed directly to raster().
Here's an example with a GeoTIFF from the rgdal package. Note that the rasterVis function is in a separate package and is called plot3D (not plot3d which is in the rgl package):
library(rgdal)
library(rasterVis)
r <- raster(system.file("pictures/cea.tif", package = "rgdal")[1])
plot3D(r)
The rasterVis package handles all the scaling and colours and provides a nice default.
If you want to delve further into the supporting packages, here's a simple example.
library(rgdal)
library(raster)
library(rgl)
## read the file with raster
r <- raster(system.file("external/test.ag", package="sp")[1])
## just use simple persp plot
persp(r)
## convert to sp's SpatialGridDataFrame (or use readGDAL directly)
## (for very large rasters this could be prohibitive in terms of memory)
sgdf <- as(r, "SpatialGridDataFrame")
## convert to R's image() format, a list with x,y vector and z matrix
x <- as.image.SpatialGridDataFrame(sgdf)
## plot with rgl, ugly but see ?surface3d for colour options etc.
surface3d(x$x, x$y, x$z)

Resources