Get Adjacency matrix for Polygons in GeoJSON using R - r

I've got a set of polygons in the GeoJSON file. They're neighborhoods in Boston. I would like to produce an adjacency matrix in CSV format, where element j,j is 1 if district i is adjacent to district j (i.e. they are touching).
I found a code in R on the internet and used for my data set (Uber Movement Dataset) as folows:
library(rgeos)
library(rgdal)
polys <- readOGR("D:/boston_taz.json")
adj <- gTouches(polys, byid = TRUE)
and got the following error:
> library(rgeos)
> library(rgdal)
> polys <- readOGR("D:/boston_taz.json")
OGR data source with driver: GeoJSON
Source: "D:\boston_taz.json", layer: "boston_taz"
with 2728 features
It has 7 fields
> adj <- gTouches(polys, byid = TRUE)
Error in RGEOSBinPredFunc(spgeom1, spgeom2, byid, "rgeos_touches") :
rgeos_binpredfunc: comparison failed
As I'm new to R, what's the issue and how do I export the resulting matrix to .csv format?

I used a zero-width buffer to clean up the topology problems in R and my problem is solved.
library(rgeos)
library(rgdal)
polys <- readOGR("D:/boston_taz.json")
polys2 <- gBuffer(polys , byid=TRUE, width=0)
adj <- gTouches(polys2, byid = TRUE, returnDense=TRUE, checkValidity=TRUE)
write.csv(adj ,"adj.csv")

Related

How can I clip a shapefile to my raster using R?

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

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

Error in as.numeric(bbox) : cannot coerce type 'S4' to vector of type 'double'

What this error means??? Maybe an error with coordinate format? Or in the polygon's format/shape?
The script is from Zizka's tutorial "Downloading occurrences from GBIF", in short I need to download occurrences from a specific group of plants that occurs inside this polygon (a multipolygon actually). The polygon is a shapefile that I created in ArcMAP.
This is the script I used to download occurrences from GBIF:
library(countrycode)
library(ConR)
library(devtools)
library(ggmap)
library(mapproj)
library(maps)
library(rgbif)
library(raster)
library(rnaturalearth)
library(sp)
library(tidyverse)
library(viridis)
library(rgdal)
library(rgeos)
library(arulesViz)
library(arules)
tax_key <- name_suggest(q = "Apocynaceae", rank = "Family")
lapply(tax_key$key, "occ_count")
tax_key <- tax_key$key[1]
occ_count(tax_key, country = "BR")
mataatlant <- readOGR('C:/Users/brena/Mata Atlântica/MA GRID', layer = 'MAGrid30')
rgeos::writeWKT(mataatlant)
study_a <- mataatlant
dat_ne <- occ_search(taxonKey = tax_key, return = "data", hasCoordinate = T,
geometry = mataatlant, limit = 50000)
*Error in as.numeric(bbox) :
cannot coerce type 'S4' to vector of type 'double'*
A simplification, but:
You have a a data type mismatch. The s4 object is a shapefile (or an R analogue, such as spatial points/polyongs data frame, or a simple_feature. A double is a field in the data table in ArcMap. You've told R to calculate the shapefile, not the field in the shapefile.

Intersect in R - miss one polygon

1. The problem
I'm trying to extract the intersection of two polygons shapes in R. The first is the watershed polygon "ws_polygon_2", and the second is the Voronoi polygons of 5 rain gauges which was constructed from the Excel sheet "DATA.xlsx", both available here: link.
The code is the following:
#[1] Montagem da tabela de coordenadas dos postos pluviométricos
library(sp)
library(readxl)
dados_precipitacao_1985 <- read_excel(path="C:/Users/.../DATA.xlsx")
coordinates(dados_precipitacao_1985) <- ~ x + y
proj4string(dados_precipitacao_1985) <- CRS("+proj=longlat +datum=WGS84")
d_prec <- spTransform(dados_precipitacao_1985, CRSobj = "+init=epsg:3857")
#[2] Coleta dos dados espaciais da bacia hidrográfica
library(rgdal)
bacia_Caio_Prado <- readOGR(dsn="C:/Users/...", layer="ws_polygon_2")
bacia_WGS <- spTransform(bacia_Caio_Prado, CRSobj = "+proj=longlat +datum=WGS84")
bacia_UTM <- spTransform(bacia_Caio_Prado, CRSobj = "+init=epsg:3857")
#[3] Poligonos de Thiessen - 1 INTERPOLAÇÃO
library(dismo)
library(rgeos)
library(raster)
library(mapview)
limits_voronoi_WGS <- c(-40.00,-38.90,-5.00,-4.50)
v_WGS <- voronoi(dados_precipitacao_1985, ext=limits_voronoi_WGS)
bc <- aggregate(bacia_WGS)
u_WGS_1 <- gIntersection(spgeom1 = v_WGS, spgeom2 = bc,byid=TRUE)
u_WGS_2 <- intersect(bc, v_WGS)
When I apply the intersect function, the variable returned u_WGS_2 is a spatial polygon data frame with only 4 features, instead of 5. The Voronoi object v_WGS has 5 features as well.
By other hand, when I apply the gIntesection function, I get 5 features. However, the u_WGS_1 object is a spatial polygon only and I loss the rainfall data.
I'd like to know if I am committing any mistake or if there is any way to get the 5 features aggregated with the rainfall data in a spatial polygon data frame through the intersect function.
My objective is to transform this spatial polygon data frame with the rainfall data for each Voronoi polygon in a raster through the rasterize function later to compare with other interpolating results and satellite data.
Look these results. The first one is when I get the SPDF (Spatial Polygon Data Frame) I want, but missing the 5º feature. The second is the one I get with all the features I want, but missing the rainfall data.
spplot(u_WGS_2, 'JAN')
plot(u_WGS_1)
2. What I've tried
I look into the ws_polygon_2 shape searching for any other unwanted polygon who would pollute the shape and guide to this results. The shape is composed by only one polygon feature, the correct watershed feature.
I tried to use the aggregate function, as above, and as I saw in this tutorial. But I got the same result.
I tried to create a SPDF with de u_WGS_1 and the d_precSpatial Point Data Frame object. Actually, I'm working on it. And if it is the correct answer to my trouble, please help me with some code.
Thank you!
This is not an issue when using st_intersection() from sf, which retains the data from both data sets. Mind that dismo::voronoi() is compatible with sp objects only, so the precipitation data needs to be available in that format, at least temporarily. If you do not feel comfortable with sf and prefer to continue working with Spatial* objects after the actual intersection, simply invoke the as() method upon the output sf object as shown below.
library(sf)
#[1] Montagem da tabela de coordenadas dos postos pluviométricos
dados_precipitacao_1985 <- readxl::read_excel(path="data/DATA.xlsx")
dados_precipitacao_1985 <- st_as_sf(dados_precipitacao_1985, coords = c("x", "y"), crs = 4326)
dados_precipitacao_1985_sp <- as(dados_precipitacao_1985, "Spatial")
#[2] Coleta dos dados espaciais da bacia hidrográfica
bacia_Caio_Prado <- st_read(dsn="data/SHAPE_CORRIGIDO", layer="ws_polygon_2")
#[3] Poligonos de Thiessen - 1 INTERPOLAÇÃO
limits_voronoi_WGS <- c(-40.00,-38.90,-5.00,-4.50)
v_WGS <- dismo::voronoi(dados_precipitacao_1985_sp, ext=limits_voronoi_WGS)
v_WGS_sf <- st_as_sf(v_WGS)
u_WGS_3 <- st_intersection(bacia_Caio_Prado, v_WGS_sf)
plot(u_WGS_3[, 6], key.pos = 1)
The missing polygon is removed because it is invalid
library(raster)
bacia <- shapefile("SHAPE_CORRIGIDO/ws_polygon_2.shp")
rgeos::gIsValid(bacia)
#[1] FALSE
#Warning message:
#In RGEOSUnaryPredFunc(spgeom, byid, "rgeos_isvalid") :
# Ring Self-intersection at or near point -39.070555560000003 -4.8419444399999998
The self-intersection is here:
zoom(bacia, ext=extent(-39.07828, -39.06074, -4.85128, -4.83396))
points(cbind( -39.070555560000003, -4.8419444399999998))
Invalid polygons are removed as they are assumed to have been produced by intersect. In this case, the invalid data was already there and should have been retained. I will see if I can fix that.

Extract shapefiles from longitude/latitude gridded data

I have some gridded data of sea surface temperature values in the Mediterranean to which I've applied clustering. I have 420 files with three columns structure (long,lat,value). The data for a particular file looks like this map
Now I want to extract the cluster areas as shapefile for postprocessing. I have found this post (https://gis.stackexchange.com/a/187800/9227) and tried to use its code like this
# Packages
library(sp)
library(rgdal)
library(raster)
# Paths
ruta_datos<-"/home/meteo/PROJECTES/VERSUS/OUTPUT/DATA/CLUSTER_MED/"
setwd("~/PROJECTES/VERSUS/temp")
# File list
files <- list.files(path = ruta_datos, pattern = "SST-cluster-mitja-mensual")
for (i in 1:length(files)){
datos<-read.csv(paste0(ruta_datos,files[i],sep=""),header=TRUE)
nclusters<-max(datos$cluster)
for (j in 1:nclusters){
clust.dat<-subset(datos, cluster == j)
coordinates(clust.dat)=~longitud+latitud
proj4string(clust.dat)=CRS("+init=epsg:4326")
pts = spTransform(clust.dat,CRS("+init=epsg:4326"))
gridded(pts) = TRUE
r = raster(pts)
projection(r) = CRS("+init=epsg:4326")
# make all values the same. Either do
s <- r > -Inf
# convert to polygons
pp <- rasterToPolygons(s, dissolve=TRUE)
# save shapefile
shname<-paste("SST-shape-",substr(files[i],27,32),"-",j,sep="")
writeOGR(pp, dsn = '.', layer = shname, driver = "ESRI Shapefile")
}
}
But the code stops for with this error message
gridded(pts) = TRUE
suggested tolerance minimum: 1
Error in points2grid(points, tolerance, round) : dimension 2
: coordinate intervals are not constant
Warning message: In points2grid(points, tolerance, round) : grid has empty
column/rows in dimension 1
I don't understand that at a certain file it says that coordinate intervals are not constant while they indeed are, original SST data from which clustering was derived are on a regular grid over the whole globe. All cluster data files have the same size, 4248 points. A sample data file is available here
What does the tolerance suggestion means? I've been looking for a solution and found some suggestion to use SpatialPixelsDataFrame but couldn't find out how to apply.
Any help would be appreciated. Thanks.
I am not an expert of geospatial data but for me, if you filter on cluster, data are indeed not on a grid. So far as I understand, you start from a grid (convex set of regularly distant points).
I tried following modifications to your code and some files are generated but I can't test whether they are correct or not.
Principle is to build the grid on all data then only filter on cluster before calling raster.
This gives:
files <- list.files(path = ruta_datos, pattern = "SST-cluster-mitja-mensual")
for (i in 1:length(files)){
datos<-read.csv(paste0(ruta_datos,files[i],sep=""),header=TRUE)
nclusters<-max(datos$cluster)
for (j in 1:nclusters){
## clust.dat<-subset(datos, cluster == j)
clust.dat <- datos
coordinates(clust.dat)=~longitud+latitud
proj4string(clust.dat)=CRS("+init=epsg:4326")
pts = spTransform(clust.dat,CRS("+init=epsg:4326"))
gridded(pts) = TRUE
## r = raster(pts)
r= raster(pts[pts$cluster==j,])
projection(r) = CRS("+init=epsg:4326")
# make all values the same. Either do
s <- r > -Inf
# convert to polygons
pp <- rasterToPolygons(s, dissolve=TRUE)
# save shapefile
shname<-paste("SST-shape-",substr(files[i],27,32),"-",j,sep="")
writeOGR(pp, dsn = '.', layer = shname, driver = "ESRI Shapefile")
}
}
So, two lines in comment and update just the line below.

Resources