Create a grid inside shapefile for kriging based on meuse.grid - r

I was trying to follow this kriging exercise and ended up going on a 6 hour adventure in an attempt to create a grid file like meuse.grid in the link. I'm very new to R and geostats in general so I'd really appreciate any help. I managed to create a SpatialPolygonsDataFrame using a shapefile to get: this
cishape <- st_read("data/files/cishape.shp")
map <- as_Spatial(cishape)
plot(map)
I then managed to get this which seems to be closer to correct although the shape is now more off:
grd <- makegrid(poly, n=10000); colnames(grd) <-c("x", "y");
grd_pts <- SpatialPoints(coords=grd, proj4string = CRS(proj4string(poly)));
grd_pts_in <- grd_pts[poly,];
gdf <- as.data.frame(coordinates(grd_pts_in));
ggplot(gdf) + geom_point(aes(x=x, y=y))
I can't seem to make this work following the kriging exercise though. When I make it to the bit where:
grd <- as(grd, "SpatialPixelsDataFrame
plot(grd), I get the error: Error in .subset2(x, i, exact = exact) : subscript out of bounds. I read that it is because my spdf is actually has no data and should use SpatialPixels instead, but then I get the error Error in matrix(FALSE, ncells[2], ncells[1]) : invalid 'nrow' value (too large or NA). So then I tried SpatialPoints instead and got this chunk.
Please help, I don't know what I'm doing wrong and I feel like I'm losing my sanity.

Related

Resample and matching raster stack using loop in R

I aim to combine biodiversity data with land cover information (rasters and vectors).
However, I need to match the resolution, extent, CRS, and dimensions of each raster (predictor variables) with my biodiversity data (answer variables). I had succeed to do it individually but there are six rasters.
Although, when I try a loop for the raster stack. I got some errors.
 
library(terra)
library(raster)
#Create a raster stack with land cover predictors:
CDI_stack<-raster::stack(list.files(path = dir_Proj1, pattern='.tif', full.names=T))
#Convert to cylindrical equal area projection
equalareaproj<-"+proj=cea +lon_0=0 +lat_ts=30 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"
crs(CDI_stack, warn=FALSE)<-equalareaproj
#Raster with standard dimension, resolution, extention and CRS
standard<-terra::subset(study_area, 2)
#Loop for the raster stack
for(i in 1:length(CDI_stack#layers)){
#Creating a single raster with each layer to maintain values
CDI_layer<-terra::rast(terra::subset(CDI_stack, i))
#Matching a raster extention individually
CDI_layer<-ext(standard)
#Cropping it with standard raster to reduce matching error
raster::crop(CDI_layer[i],standard)
#Resample resolution
terra::resample(CDI_layer[i], standard, method= "near", threads= T)
#Write the raster:
return(writeRaster(Resampled_layer,
filename=paste0("~/Land use/Chronic_Anthropogenic_Disturbance_Surface/", CDI_layer[i]),
format="GTiff", overwrite=TRUE))
}
I found these errors:
Error in h(simpleError(msg, call)) :
error evaluating argument 'x' in method selection for function 'crop': 'this S4 class is not subsettable
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘crop’ for signature ‘"numeric"’
I would like to know if there's any complication to use raster stack or whether I am doing any code step wrongly. I expect to found the correction on the code or of the use of class object.
Please, I hope for your support. Thank you!
G.
Thank you for your advice, Mr. Hijimans.
I found too many errors.
When we do it directly with the raster stack the R returns that the method for the function 'resample' does not work on RasterStack class (see below).
As a stack can have multiple layers, the loop simplified the process rather to work on each one of them.
I preferred to work with a list from the raster stack than the stack, it worked better in the loop.
Also, I used a vector to crop the raster, it preserved raster values (avoiding return NA).
rc <- terra::resample(CDI_stack, standard, method= "bilinear", threads= T)
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘resample’ for signature ‘"RasterStack", "SpatRaster"’
#Create a list from the stack with land cover predictors:
CDI_list<-terra::as.list(CDI_stack)
rm(study_area,CDI_stack)
#Create a list to store the results
results <- list()
#Loop for each SpatRaster from the list
for(i in 1:length(CDI_list)) {
r<-rast(CDI_list[[i]]) # create a raster for each layer
ext(r) <-ext(standard) # redefine extension for each layer
#Crop rasters using the vector to avoid 'NA' values
rc <- terra::crop(r, standard_vec)
#Resample rasters following standard parameters
rc <- terra::resample(rc, standard, method= "bilinear", threads= T)
#Rewrite the list layers with the result
results[[i]] <- rc
}
#Check the values
results[[4]]
#Rasterize the list to save it as a data frame
resampled<-rast(results)
df<-as.data.frame(resampled)
summary(df)
#Save the data frame in the project directory
data.table::fwrite(df, "~/Land use/DATASETS/resampled.csv")
It should be easy enough to find out what is going wrong when you run the code line by line; including inside the for-loop (set i to 1 or whatever the valye is when the error occurs).
You will see that this fails:
CDI_layer <- ext(standard)
raster::crop(CDI_layer[i],standard)
Because CDI_layer[i] is a single number.
There are other things that are awkward. Especially, just use "terra", do not also use "raster" at the same time to avoid confusion.
Seeing your answer it would seem that you can do all of this in two lines
CDI_stack <- terra::rast(files)
rc <- terra::resample(CDI_stack, standard, method= "bilinear", threads= T)
df <- as.data.frame(rc)

Using R intersections to create a polygons-inside-a-polygon key using two shapefile layers

The data
I have two shapefiles marking the boundaries of national and provincial electoral constituencies in Pakistan.
The objective
I am attempting to use R to create a key that will generate a list of which provincial-level constituencies are "contained within" or otherwise intersecting with which national-level constituencies, based on their coordinates in this data. For example, NA-01 corresponds with PA-01, PA-02, PA-03; NA-02 corresponds with PA-04 and PA-05, etc. (The key will ultimately be used to link separate dataframes containing electoral results at the national and provincial level; that part I've figured out.)
I have only basic/intermediate R skills learned largely through trial and error and no experience working with GIS data outside of R.
The attempted solution
The closest solution I could find for this problem comes from this guide to calculating intersection areas in R. However, I have been unable to successfully replicate any of the three proposed approaches (either the questioner's use of a general TRUE/FALSE report on intersections, or the more precise calculations of area of overlap).
The code
# import map files
NA_map <- readOGR(dsn = "./National_Constituency_Boundary", layer = "National_Constituency_Boundary")
PA_map <- readOGR(dsn = "./Provincial_Constituency_Boundary", layer = "Provincial_Constituency_Boundary")
# Both are now SpatialPolygonsDataFrame objects of 273 and 577 elements, respectively.
# If relevant, I used spdpylr to tweak some of data attribute names (for use later when joining to electoral dataframes):
NA_map <- NA_map %>%
rename(constituency_number = NA_Cons,
district_name = District,
province = Province)
PA_map <- PA_map %>%
rename(province = PROVINCE,
district_name = DISTRICT,
constituency_number = PA)
# calculate intersections, take one
Results <- gIntersects(NA_map, PA_map, byid = TRUE)
# this creates a large matrix of 157,521 elements
rownames(Results) <- NA_map#data$constituency_number
colnames(Results) <- PA_map#data$constituency_number
Attempting to add the rowname/colname labels, however, gives me the error message:
Error in dimnames(x) <- dn :
length of 'dimnames' [1] not equal to array extent
Without the rowname/colname labels, I'm unable to read the overlay matrix, and unsure how to filter them so as to produce a list of only TRUE intersections that would help make a NA-PA key.
I also attempted to replicate the other two proposed solutions for calculating exact area of overlap:
# calculate intersections, take two
pi <- intersect(NA_map, PA_map)
# this generates a SpatialPolygons object with 273 elements
areas <- data.frame(area=sapply(pi#polygons, FUN = function(x) {slot(x, 'area')}))
# this calculates the area of intersection but has no other variables
row.names(areas) <- sapply(pi#polygons, FUN=function(x) {slot(x, 'ID')})
This generates the error message:
Error in `row.names<-.data.frame`(`*tmp*`, value = c("2", "1", "4", "5", :
duplicate 'row.names' are not allowed
In addition: Warning message:
non-unique value when setting 'row.names': ‘1’
So that when I attempt to attach areas to attributes info with
attArrea <- spCbind(pi, areas)
I get the error message
Error in spCbind(pi, areas) : row names not identical
Attempting the third proposed method:
# calculate intersections, take three
pi <- st_intersection(NA_map, PA_map)
Produces the error message:
Error in UseMethod("st_intersection") :
no applicable method for 'st_intersection' applied to an object of class "c('SpatialPolygonsDataFrame', 'SpatialPolygons', 'Spatial', 'SpatialPolygonsNULL', 'SpatialVector')"
I understand that my SPDF maps can't be used for this third approach, but wasn't clear from the description what steps would be needed to transform it and attempt this method.
The plea for help
Any suggestions on corrections necessary to use any of these approaches, or pointers towards some other method of figuring this, would be greatly appreciated. Thanks!
Here is some example data
library(raster)
p <- shapefile(system.file("external/lux.shp", package="raster"))
p1 <- aggregate(p, by="NAME_1")
p2 <- p[, 'NAME_2']
So we have p1 with regions, and p2 with lower level divisions.
Now we can do
x <- intersect(p1, p2)
# or x <- union(p1, p2)
data.frame(x)
Which should be (and is) the same as the original
data.frame(p)[, c('NAME_1', 'NAME_2')]
To get the area of the polygons, you can do
x$area <- area(x) / 1000000 # divide to get km2
There are likely to be many "slivers", very small polygons because of slight variations in borders. That might not matter to you.
But another approach could be matching by centroid:
y <- p2
e <- extract(p1, coordinates(p2))
y$NAME_1 <- e$NAME_1
data.frame(y)
Your code isn't self-contained, so I didn't try to replicate the errors you report.
However, getting the 'key' you want is very simple using the sf package (which is intended to supercede rgeos, rgdal and sp in the near future). See here:
library(sf)
# Download shapefiles
national.url <- 'https://data.humdata.org/dataset/5d48a142-1f92-4a65-8ee5-5d22eb85f60f/resource/d85318cb-dcc0-4a59-a0c7-cf0b7123a5fd/download/national-constituency-boundary.zip'
provincial.url <- 'https://data.humdata.org/dataset/137532ad-f4a9-471e-8b5f-d1323df42991/resource/c84c93d7-7730-4b97-8382-4a783932d126/download/provincial-constituency-boundary.zip'
download.file(national.url, destfile = file.path(tempdir(), 'national.zip'))
download.file(provincial.url, destfile = file.path(tempdir(), 'provincial.zip'))
# Unzip shapefiles
unzip(file.path(tempdir(), 'national.zip'), exdir = file.path(tempdir(), 'national'))
unzip(file.path(tempdir(), 'provincial.zip'), exdir = file.path(tempdir(), 'provincial'))
# Read map files
NA_map <- st_read(dsn = file.path(tempdir(), 'national'), layer = "National_Constituency_Boundary")
PA_map <- st_read(dsn = file.path(tempdir(), 'provincial'), layer = "Provincial_Constituency_Boundary")
# Get sparse list representation of intersections
intrs.sgpb <- st_intersects(NA_map, PA_map)
length(intrs.sgpb) # One list element per national constituency
# [1] 273
print(intrs.sgpb[[1]]) # Indices of provnicial constituencies intersecting with first national constituency
# [1] 506 522 554 555 556
print(PA_map$PROVINCE[intrs.sgpb[[1]]])[1] # Name of first province intersecting with first national constituency
# [1] KHYBER PAKHTUNKHWA

Plotting netcdf file with raster package leads to distorted representation, R

I want to properly plot this netcdf file: http://www.filedropper.com/sshgridsv16092015060412nc (Downloaded originally from here: https://opendap.jpl.nasa.gov/opendap/allData/merged_alt/L4/cdr_grid/contents.html)
But run into issues:
I should be able to just plot the raster (the SLA variable):
library(RNetCDF)
library(raster)
library(maptools)
d <- raster("ssh_grids_v1609_2015060412.nc.nc4", varname = "SLA")
plot(d)
#plot SLA
But the result is very weird as you can see with the provided file.
Especially when plotting a world map on top:
data(wrld_simpl)
plot(wrld_simpl, add = T)
They don't match at all :/
So I thought maybe the problem is with the longitude (ranging from 4.839944e-09 to 360)
Then I read that raster::rotate(d)
should be perfect for that (to get longitude to -180 to 180), but it won't let me. I get this warning message:
Warning message:
In .local(x, ...) :
this does not look like an appropriate object for this function
and
plot(d)
still looks the same.
Any advice would be greatly appreciated!
Cheers
The Netcdf file is not only "rotated" in longitude but x and y are also at the wrong position. The way it has been entered in the netcdf is not usual apparently.
I downloaded the netcdf directly on the OpenDap server because your filedropper link seems to be corrupt.
Anyway, here is my proposition:
library(raster)
library(maptools)
d <- raster("ssh_grids_v1609_2015060412.nc.nc4", varname = "SLA")
# transpose x to y and double flip the map
m.r <- flip(flip(t(d), direction = "y"), direction = "x")
# then rotate from 0:360 to -180:180
rm.r <- rotate(m.r)
data(wrld_simpl)
plot(rm.r)
plot(wrld_simpl, add = T)

Why does R think the projection data are different?

I'm working with satellite tracked animals and have a load of relocation data.
So I have my map data and relocations as SpatialPointsDataFrames and when I ask
if proj4string(map)==proj4string(locs) I get TRUE.
But when I try the count.points function as follows
cp <- count.points(locs, map)
I get the following error
Error in count.points(SpatialPoints(x), w) :
different proj4string in w and xy
Does anyone have any ideas on why this is the case?
Edit Code:
load("mydata")
map = mydata$map
map
mimage(map)
locs= mydata$relocs
locs
image(map)
points(locs, col=as.numeric(slot(locs, "data")[,1]), pch=16)
cp <- count.points(locs, map)
Reproducible example would go a long, long way here. But generally speaking R's comparison of projection strings is approximately verbatim. So if there's an extra space or so forth, it will fail.
Given the out for proj4string(map), proj4string(locs), proj4string(SpatialPoints(locs)) in the comment, particularly that proj4string(SpatialPoints(locs)) is NA, I'd say that count.points is dropping the proj4string when it changes to a SpatialPoints object. I think the way to coerce a SPDF to SP while keeping the projection string is via as(x,"SpatialPoints").... Try using trace to insert that into count.points?

Is it possible to overlay SpatialLinesDataFrame and SpatialPolygonDataFrame

I am wondering if this is possible to do this R .
I have one data as SpatialLinesDataFrame and another as spatialPolygonDataFrame. Is it possible to overlay these two data ?
When I try to overlay these I get the following error:
jd <- overlay(res,hello)
Error in function (classes, fdef, mtable) : unable to find an inherited method for function
‘overlay’ for signature ‘"SpatialLinesDataFrame", "SpatialPolygonsDataFrame"’
In the above code res is the SpatialLinesDataFrame and hello is SpatialPolygonDataFrame.
I have an shapefile and then I have data points with x,yand z
coordinates. I want to show the contour lines on the shapefile.
The procedure I used is using akima package to do the interpolation. The
code I used to interpolate is
fld <- interp(x,y,z)
Then I changed this to spatial object by using following code:
res <-ContourLines2SLDF(contourLines(fld))
The above command would store the contourlines as spatial data.
Then I read the shapefile and I plot both shapefile and res as follows:
p1 <-
spplot(hello,sp.layout=list(list("sp.lines",res)),col="blue",lwd=0,fill="grey",colorkey=F)
p1
"hello" is my shapefile and "res" is the object I created as shown above.
The problem is contour stored in "res" extends beyond the shapefile. So I
want to clip that contour with the shapefile and only display the contour
within the shapefile area.
So I am looking for a way to clip the contour layer with the polygon layer.
I have attached the image I got with my code.
In the image you can see the lines out of the shapefile. I also want to know
how can I display the contour levels on the map.
Thank you so much.
Jdbaba
I also want to know what does overlay does exactly. Does it intersect the area of both the data ?
Thank you.
It sounds like you're trying to clip your lines to the polygon extent. Use gIntersection from the rgeos package. Here's a reproducible example:
library(rgeos)
xx <- SpatialPoints(coords=matrix(data=c(0,0), nrow=1))
xx <- gBuffer(spgeom=xx, width=1)
yy <- SpatialLines(list(Lines(Line(matrix(c(-1,1,-1,1), nrow=2)), ID=1)))
zz <- gIntersection(yy, xx)
You can overlay the plot like so:
plot(xx)
plot(zz, add = TRUE, col = "blue")
Noah's answer has worked quite well for me. However, the output of his answer is a SpatialLines object, which cannot be saved as a shape file.
My two cents here is about how you can convert your SpatialLines object into a SpatialLinesDataFrame and save it as a shape file.
res.df <- fortify(res) # create data frame of res, your original SpatialLinesDataFrame
data <- data.frame(id = unique(res.df$id)) # get ids of road segments
rownames(data) <- data$id
# transform SpatialLines object into SpatialLinesDataFrame
zzSpatialLineDF <- SpatialLinesDataFrame(zz, data) # convert zz object keeping road ids
# 5 Save Shape File to your working directory
writeOGR(zzSpatialLineDF, dsn = '.', layer ='zzSpatialLineDF', driver = 'ESRI Shapefile')

Resources