Spatial Polygon sampling error in R - r

I have a shape file of 200 counties. How should I sample in order to subset counties from the existing 200? I have tried using the below R code:
library(maptools)
TXcounties <- readShapePoly("C:/Users/Rvg296/Downloads/TXCountiesShapeFiles/TXCounties.shp")
idx <- sample(1:250, 25, replace = FALSE)
df.TXcounties <- as.data.frame(TXcounties)
SpatialPolygonsDataFrame(idx, df.TXcounties).
But this is throwing an error like:
Error in SpatialPolygonsDataFrame(idx, df.TXcounties) : trying to get slot "polygons" from an object of a basic class ("integer") with no slots

The problem is that you are using idx, an integer vector, as the first argument for SpatialPolygonsDataFrame(), but this function needs a spatial polygons object as its first argument. In any case, you should be able to do the whole thing a lot more easily with something like this:
result <- TXcounties[idx,]

Related

How to create a list of several rasters from a crop and mask (cut) from shapefile in R

I have 14 raster files from each year of land use. I would like to crop these rasters using my shapefile area of interest. With these cut rasters I would like to create a list where each element represents each year cut by the shapefile.
I tried in a very simple and fast way using the for, crop and mask commands, but without success.
my data exemplo:
raster and shape files : https://drive.google.com/file/d/1IOGWZ3_ckKj3UoZVd7ikR5l9n04xd6He/view?usp=sharing
my code
library(raster)
library(rgdal)
library(sf)
setwd('dir')
raster_solo_2005<-raster('utm-50-2005.tif')
raster_solo_2006<-raster('utm-50-2006.tif')
raster_solo_2007<-raster('utm-50-2007.tif')
raster_solo_2008<-raster('utm-50-2008.tif')
raster_solo_2009<-raster('utm-50-2009.tif')
raster_solo_2010<-raster('utm-50-2010.tif')
raster_solo_2011<-raster('utm-50-2011.tif')
raster_solo_2012<-raster('utm-50-2012.tif')
raster_solo_2013<-raster('utm-50-2013.tif')
raster_solo_2014<-raster('utm-50-2014.tif')
raster_solo_2015<-raster('utm-50-2015.tif')
raster_solo_2016<-raster('utm-50-2016.tif')
raster_solo_2017<-raster('utm-50-2017.tif')
raster_solo_2018<-raster('utm-50-2018.tif')
#list raster
list_raster<-as.list(raster_solo_2005, raster_solo_2006, raster_solo_2007, raster_solo_2008, raster_solo_2009, raster_solo_2010, raster_solo_2011, raster_solo_2012, raster_solo_2013, raster_solo_2014, raster_solo_2015, raster_solo_2016, raster_solo_2017, raster_solo_2018)
#shapefile
shp_area<-sf::st_read('500m_utm.shp')
#creat list empity
list_raster_cut<-list()
#loop operation
for(i in 1:10){
# crop e mask
list_raster_cut[[i]] <- list_raster %>%
raster::crop(shp_area)%>%
raster::mask(shp_area)
}
Update: exit error
Error in h(simpleError(msg, call)) : error evaluating argument 'x' when selecting method for function 'mask': 'unable to find an inherited method for function 'crop' for signature '"list" , "sf"''
The problem is that you need to also subset the list_raster object inside the for loop.
list_raster_cut[[i]] <- list_raster[[i]] %>%
raster::crop(shp_area)%>%
raster::mask(shp_area)

R sf: Points of LinearRing do not form a closed linestring

I am trying to calculate the centroids of a set of polygons.
My dataset, geodata, contains five columns including one geometry column of class sfc_GEOMETRY, with 45759 rows.
When I run sf::st_centroid(geodata), I get the following message
Error in CPL_geos_op("centroid", x, numeric(0), integer(0), numeric(0), : Evaluation error: IllegalArgumentException: Points of LinearRing do not form a closed linestring.
In addition: Warning messages:
1: In st_centroid.sf(geodata) :
st_centroid assumes attributes are constant over geometries of x
2: In st_centroid.sfc(st_geometry(x), of_largest_polygon = of_largest_polygon) :
st_centroid does not give correct centroids for longitude/latitude data
Should I run a loop to detect which geometry is not closed?
Is this a problem with the class of my geometry? Should it be sfc_MULTIPOLYGON?
Possible solution:
I was encountering this problem when reading in a list of files through a loop. The loop would read in the files and then rbind them together into geodata, and then calculate the centroid:
for(i in 1:length(list)){
file <- st_read(list[i])
geodata <- rbind(geodata, file) #geodata is here a void sf object
}
geocent <- st_centroid(geodata)
When I calculated the centroids within the loop (for each file in the list), the error disappeared.
for(i in 1:length(list)){
file <- st_read(list[i])
file <- st_centroid(file)
geocent <- rbind(geodata, file) #geodata is here a void sf object
}
Hence, I think the problem lay in the binding operation.
Perhaps I had not defined my void sf object in the right manner.
Perhaps rbind was not the appropriate function, or I should have specified its parameters.
There's no need to run a loop to find which geometry is bad. The st_is_valid() function should tell you which row(s) have the problem.
It looks like one of your geometries might be made up of an incorrect number of points.
More info about finding and fixing the problem at r-spatial: https://www.r-spatial.org/r/2017/03/19/invalid.html

Convert SpatialCollections to SpatialPolygonsDataFrame in R

I am struggling to convert an object of class SpatialCollections to a SpatialPolygonsDataFrame object.
My input files are both shapefiles and SpatialPolygonsDataFrame objects. They can be accessed here.
I do an intersection of both objects:
SPDF_A <- shapefile("SPDF_A")
SPDF_B <- shapefile("SPDF_B")
intersection <- gIntersection(gBuffer(SPDF_A, width=0), gBuffer(SPDF_B, width=0))
The result is:
> intersection
class : SpatialCollections
Setting gBuffer(... , byid=T) or gBuffer(... , byid=F) seems to make no difference.
I use gIntersection and gBuffer(... , width=0) insetead of intersect in order to avoid geometrical problems (Self-intersection).
This is part of a larger loop. I need to get the intersection as SpatialPolygonsDataFrame because it will be saved as shp file in a following step.
writeOGR(intersection, ".", layer=paste0("Int_SPDF_A-SPDF_B"), driver="ESRI Shapefile")
This is not possible from a SpatialCollections object. In order to convert this to a SpatialPolygonsDataFrame I tried:
intersection <- as(intersection ,"SpatialPolygonsDataFrame")
intersection <- SpatialPolygonsDataFrame(intersection)
intersection <- readOGR(intersection, layer = "intersection")
Nothing works. Does anybody have a solution? Thanks a lot!
First of all, according to the documentation SpatialCollections is kind of a container format that can "hold SpatialPoints, SpatialLines, SpatialRings, and SpatialPolygons (without attributes)". If you need the data frame part of your SpatialPolygonsDataFrame ("attribute table" in GIS language), you'll have to work around that somehow. If, on the other hand, you're only interested in the spatial information (the polygons without the data attached to them) try the following:
str(intersection, max.level = 3)
suggests that the #polyobj is nothing but a SpatialPolygons object. Hence
mySpoly <- intersection#polyobj
should do the trick and
class(mySpoly)
suggests that we indeed now have a SpatialPolygons.
You need to convert that to a SpatialPolygonsDataFrame before exporting:
mySpolyData <- as(mySpoly, "SpatialPolygonsDataFrame")
writeOGR(mySpolyData, ".", layer=paste0("Int_SPDF_A-SPDF_B"), driver="ESRI Shapefile")

Extract raster by a list of SpatialPolygonsDataFrame objects in R

I am trying to extract summed raster cell values from a single big file for various SpatialPolygonsDataFrames (SPDF) objects in R stored in a list, then add the extracted values to the SPDF objects attribute tables. I would like to iterate this process, and have no idea how to do so. I have found an efficient solution for multiple polygons stored in a single SPDF object (see: https://gis.stackexchange.com/questions/130522/increasing-speed-of-crop-mask-extract-raster-by-many-polygons-in-r), but do not know how to apply the crop>mask>extract procedure to a LIST of SPDF objects, each containing multiple polygons. Here is a reproducible example:
library(maptools) ## For wrld_simpl
library(raster)
## Example SpatialPolygonsDataFrame
data(wrld_simpl) #polygon of world countries
bound <- wrld_simpl[1:25,] #country subset 1
bound2 <- wrld_simpl[26:36,] #subset 2
## Example RasterLayer
c <- raster(nrow=2e3, ncol=2e3, crs=proj4string(wrld_simpl), xmn=-180,
xmx=180, ymn=-90, ymx=90)
c[] <- 1:length(c)
#plot, so you can see it
plot(c)
plot(bound, add=TRUE)
plot(bound2, add=TRUE, col=3)
#make list of two SPDF objects
boundl<-list()
boundl[[1]]<-bound1
boundl[[2]]<-bound2
#confirm creation of SPDF list
boundl
The following is what I would like to run for the entire list, in a forloop format. For a single SPDF from the list, the following series of functions seem to work:
clip1 <- crop(c, extent(boundl[[1]])) #crops the raster to the extent of the polygon, I do this first because it speeds the mask up
clip2 <- mask(clip1, boundl[[1]]) #crops the raster to the polygon boundary
extract_clip <- extract(clip2, boundl[[1]], fun=sum)
#add column + extracted raster values to polygon dataframe
boundl[[1]]#data["newcolumn"] = extract_clip
But when I try to isolate the first function for the SPDF list (raster::crop), it does not return a raster object:
crop1 <- crop(c, extent(boundl[[1]])) #correctly returns object class 'RasterLayer'
cropl <- lapply(boundl, crop, c, extent(boundl)) #incorrectly returns objects of class 'SpatialPolygonsDataFrame'
When I try to isolate the mask function for the SPDF list (raster::mask), it returns an error:
maskl <- lapply(boundl, mask, c)
#Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘mask’ for signature ‘"SpatialPolygonsDataFrame", "RasterLayer"’
I would like to correct these errors, and efficiently iterate the entire procedure within a single loop (i.e., crop>mask>extract>add extracted values to SPDF attribute tables. I am really new to R and don't know where to go from here. Please help!
One approach is to take what is working and simply put the desired "crop -> mask -> extract -> add" into a for loop:
for(i in seq_along(boundl)) {
clip1 <- crop(c, extent(boundl[[i]]))
clip2 <- mask(clip1, boundl[[i]])
extract_clip <- extract(clip2, boundl[[i]], fun=sum)
boundl[[i]]#data["newcolumn"] <- extract_clip
}
One can speed-up the loop with parallel execution, e.g., with the R package foreach. Conversely, the speed gain of using lapply() instead of the for loop will be small.
Why the error occurs:
cropl <- lapply(boundl, crop, c, extent(boundl))
applies the function crop() to each element of the list boundl. The performed operation is
tmp <- crop(boundl[[1]], c)
## test if equal to first element
all.equal(cropl[[1]], tmp)
[1] TRUE
To get the desired result use
cropl <- lapply(boundl, function(x, c) crop(c, extent(x)), c=c)
## test if the first element is as expected
all.equal(cropl[[1]], crop(c, extent(boundl[[1]])))
[1] TRUE
Note:
Using c to denote an R object is a bade choice, because it can be easily confused with c().

export khrud object from kernelUD to raster

In R, how can I export a khrud object from function kernelUD in package adehabitat to a raster file (geoTiff)?
I tried following this thread (R: how to create raster layer from an estUDm object) using the code here:
writeRaster(raster(as(udbis1,"SpatialPixelsDataFrame")), "udbis1.tif")
where udbis1 is a khrud object, but I get "Error in as(udbis1, "SpatialPixelsDataFrame") : no method or default for coercing “khrud” to “SpatialPixelsDataFrame."
I think the issue may be that the old thread was before an update to the adehabitat package changed the data format from estUD to khrud. Maybe?
You do not provide a reproducible example. The following works for me:
library(adehabitatHR)
library(raster)
data(puechabonsp)
loc <- puechabonsp$relocs
ud <- kernelUD(loc[, 1])
r <- raster(as(ud[[1]], "SpatialPixelsDataFrame"))
writeRaster(r, filename = file.path(tempdir(), "ud1.tif"))
AdehabitatHR solutions work well for data that are in the required format or when using multiple animals. Though when wanting to create KDE with data organized differently or for only one source, it can be frustrating. For some reason, #johaness' answer doesn't work for my case so here is an alternative solution that avoids the headaches of going into adehabitatHR's innards.
library(adehabitatHR)
library(raster)
# Recreating an example for only one animal
# with a basic xy dataset like one would get from tracking
loc<-puechabonsp$relocs
loc<-as.data.frame(loc)
loc<-loc[loc$Name=="Brock",]
coordinates(loc)<-~X+Y
ud<-kernelUD(loc)
# Extract the UD values and coordinates into a data frame
udval<-data.frame("value" = ud$ud, "lon" = ud#coords[,1], "lat" = ud#coords[,2])
coordinates(udval)<-~lon+lat
# coerce to SpatialPixelsDataFrame
gridded(udval) <- TRUE
# coerce to raster
udr <- raster(udval)
plot(udr)

Resources