Extracting points with polygon in R - r

I'm trying to extract points by a polygon using the 'sp' package function 'over'
library(sp)
library(rgeos)
#my polygon plgn (many polygon features in one)
plot(plgn)
proj4string(plgn) = CRS("+proj=utm +zone=46 +datum=WGS84 +units=m +no_defs")
#giving spatial reference to point data d
coordinates(d) <- ~X+Y
proj4string(d) = CRS("+proj=utm +zone=46 +datum=WGS84 +units=m +no_defs")
#USE overlay (there are many NAs)
overlay=d[!is.na(over(d, plgn)),]
Unfortunately, I'm getting an ERROR
Error in d[!is.na(over(d, plgn)), ] :
matrix argument not supported in SpatialPointsDataFrame selection
Any idea?? Is it because my polygon contains 100s of features?

Your plgn is a SpatialPolygonsDataFrame, and as such, is.na(over(d, plgn)) returns a logical matrix. This cannot be used to subset your SpatialPoints*. You can do the following to convert the logical matrix to a vector that the subsetting operation can accommodate:
d[complete.cases(over(d, plgn)), ]

Related

How to project Hydrologic Rainfall Analysis Data (MPE/AHPS) raster to a usable format?

Apparently NOAA and the NWS use a non-traditional projection for some of their rainfall data and don't offer a lot of help in terms of projecting it to a traditional format for other users. I've had a bit of success in getting the raster to overlay for part of the United States but it still isn't quite right.
I'm hoping someone can help me decipher what I am missing and correct the projection of this data.
You can find more information of this data here: https://polyploid.net/blog/?p=216
https://water.weather.gov/precip/download.php
library(tidyverse)
library(raster)
library(rgdal)
library(sp)
setwd("C:/Users/MPE_Data/")
file_list <- list.files("201809")
grib0<-raster::brick("201809//ST4_2018091307_24h.nc", varname="APCP_SFC")[[1]]
grib0#crs
crs(grib0) <- "+proj=longlat +a=6371200 +b=6371200 +no_defs"
crs(grib0) <- "+proj=stere +lat_0=90 +lat_ts=60 +lon_0=-105 +x_0=0 +y_0=0 +a=6371200 +b=6371200 +units=m +no_defs"
us_shp <- rgdal::readOGR("C:/Users/cb_2017_us_state_500k/US_clipped.shp")
shp <- rgdal::readOGR("C:/Users/nc_sc_counties_wgs1984.shp")
wgs<-"+proj=longlat +datum=WGS84 +ellps=WGS84 +no_defs"
wgsraster <- projectRaster(grib0, crs=wgs)
plot(wgsraster)
shp <- spTransform(shp, CRS(wgs))
us_shp <- spTransform(us_shp, CRS(wgs))
plot(shp,add=TRUE)
plot(us_shp,add=TRUE)
I couldn't find your exact map but here is an example using recent precipitation data. You don't need to assign a CRS as the netCDF file already has a CRS associated with it, you can simply projectRaster. Also the NOAA website has the option to download to geoTIFF which I would recommend if you are more comfortable with that.
require(raster)
require(ncdf4)
require(maptools)
data(wrld_simpl)
us_shp=wrld_simpl[which(wrld_simpl$NAME=="United States"),]
rs=raster::brick("./nws_precip_1day_20200509_netcdf/nws_precip_1day_20200509_conus.nc",varname="observation")[[1]]
rs#crs ##note already has a crs associated with it
+proj=stere +lat_0=90 +lat_ts=60 +lon_0=-105 +x_0=0 +y_0=0 +a=6371200
+b=6371200 +units=m +no_defs
##assign the pixels with -10000 to NA.
NAvalue(rs) = -10000
##reproject to longlat WGS84
rs=projectRaster(rs,crs=crs(us_shp))
plot(rs,col=rainbow(100))
lines(us_shp)
##note the data extends outside the bounds of country
##use mask to remove data that is not over the land area
rs=mask(rs,us_shp)
plot(rs,col=rainbow(100)
lines(us_shp)
Note that the maximum value of rs changed from 7.8 to 7.0 due to the bilinear interpolation method used in projectRaster. You need to consider whether you require bilinear or nearest neighbour interpolation and if you need to be specific about the output raster resolution and extent I would suggest supplying a model raster for the to argument.
Edited to incorporate #Robert Hijmans' suggestion.

I downloaded shapefile but merging with internal dataset based on geometry fails

Apologies as i'm a little new to GIS features within R, so any help and explanation would be very helpful!
I have downloaded this shape file (Simple Feature Polygon) from source like so:
fire <-tempfile()
download.file("http://frap.fire.ca.gov/webdata/data/statewide/fhszs.sn.zip",destfile = fire)
unzip(fire,exdir = ".")
fire_map<-read_shape("fhszs06_3.shp")
Map has small polygons based on Hazard code (i.e.: 1,2,3)
I also have an internal dataframe that is about 15 variables with 3584 rows, I also have lat/lon for all points (commercial properties in california) that I'm trying to convert to either spatial points DF or simple feature in order to figure out which properties lie within a hazard code.
Example of property file:
ln_bal<- c(500000,200000,6000000,12000,130000)
ln_city <-c('Ventura','Torrance','Buena Park','Concord','Lake View Terrace')
lon <- c(-119.213504,-118.311072,-117.985452,-122.057139,-116.893845)
lat <-c(34.278122,33.844817,33.846594,37.979995,32.844287)
cmbs3 <- data.frame(ln_bal,ln_city,lon,lat)
I think my problem is getting the correct CRS and then matching with the shape file.
The CA Fire map has the following:
epsg (SRID): NA
proj4string: +proj=aea +lat_1=34 +lat_2=40.5 +lat_0=0 +lon_0=-120 +x_0=0 +y_0=-4000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
I've Tried sf_intersect by creating a SF points DF:
fire_map <-st_read("fhszs06_3.shp")%>%
st_transform(4326) #need to set CRS the same as your dataframe below
#transforms coordinates to ellips code and creates matching values with fire_map:
proj4string(cmbs3)<-CRS("+proj=longlat +datum=WGS84")
cmbs3 <- spTransform(cmbs3, CRS("+proj=utm +zone=51 ellps=WGS84"))
#fire_map is a simple feature data frame need to convert our data to this, and then match
cmbs3<-st_as_sf(cmbs3,precision=0)
cmbs3<-st_set_crs(cmbs3,4326)
inters <- st_intersection(cmbs3,fire_map)
Expected (potential) Results:
ln_bal ln_city lon lat HAZ_CODE HAZ_CLASS
12000 Concord -122.057139 37.97 1 Moderate

R and Export raster extent as esri shapefile

I am working with a raster dataset in R and would like to make a polygon of its extent and then export this as an ESRI shapefile. My problem, or at least what I think is the problem, occurs when I try to export the spatial polygon dataframe as I get the following error:
Error in writeOGR(p, ".", "xyz_extent", driver="ESRI Shapefile") :
obj must be a SpatialPointsDataFrame, SpatialLinesDataFrame or
SpatialPolygonsDataFrame
My script follows. Please note, I have a beginner skillset when working with spatial data in R so I do ask that answers be well described. Thank you in advance to those that chime in.
Script:
library(raster)
xyz <- raster("xyz.asc")
crs(xyz)
# CRS arguments: +proj=tmerc +lat_0=0 +lon_0=-115 +k=0.9992 +x_0=500000 +y_0=0 +datum=NAD83 +units=m +no_defs +ellps=GRS80 +towgs84=0,0,0
e <- extent(xyz)
p <- as(e, 'SpatialPolygons')
crs(p) <- crs(xyz)
library(rgdal)
writeOGR(p, ".", "xyz_extent", driver="ESRI Shapefile")
The error occurs because you have a SpatialPolygons, not a SpatialPolygonsDataFrame object. An easy way around this is to use the shapefile function instead.
library(raster)
xyz <- raster()
e <- extent(xyz)
p <- as(e, 'SpatialPolygons')
crs(p) <- crs(xyz)
shapefile(p, "xyz_extent.shp")
And you can read the file again with the same function
x <- shapefile("xyz_extent.shp")

Projection error with autoKrige function

I have a problem with autoKrig function and I try to make a reproducible example here:
library(automap)
library(raster)
library(dismo)
bio <- getData("worldclim", var="bio", res=10)
bio1 <- raster(bio, layer=1)
bio12 <- raster(bio, layer=12)
predictors <- stack(bio1, bio12)
bg <- randomPoints(bio1, 50)
data <- extract(predictors, bg)
data <- cbind(bg,data)
data <- data.frame(data)
coordinates(data)=~x+y
proj4string(data) = CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
kg <- autoKrige(bio1~bio12, data, new_data=predictors)
This will result in:
Error in autoKrige(bio1 ~ bio12, data, new_data = predictors) :
Either input_data or new_data is in LongLat, please reproject.
input_data: +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
new_data: +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
I get the same error with my original data. I appreciate any help.
If you read the help file, it will tell you why it is throwing that error.
autoKrige performs some checks on the coordinate systems of input_data
and new_data. If one or both is NA, it is assigned the projection of
the other. If they have different projections, an error is raised.
If one or both has a non-projected system (i.e. latitude-longitude), an error is raised. This error is raised because 'gstat does use
spherical distances when data are in geographical coordinates, however
the usual variogram models are typically not non-negative definite on
the sphere, and no appropriate models are available' (Edzer Pebesma on
r-sig-geo).
It looks like you need to project your data before calling autoKrige.

Map raw data and mean data based on the shapefile

sI have the dataset (pts) like this:
x <- seq(-124.25,length=115,by=0.5)
y <- seq(26.25,length=46,by=0.5)
z = 1:5290
longlat <- expand.grid(x = x, y = y) # Create an X,Y grid
pts=data.frame(longlat,z)
names(pts) <- c( "x","y","data")
I knew that I can map the dataframe (pts) into a map by doing:
library(sp)
library(rgdal)
library(raster)
library(maps)
coordinates(pts)=~x+y
proj4string(pts)=CRS("+init=epsg:4326") # set it to long, lat
pts = spTransform(pts,CRS(" +init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0"))
pts <- as(pts, "SpatialPixelsDataFrame")
r = raster(pts)
projection(r) = CRS(" +init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")
plot(r)
map("usa",add=T)
Now I would like to create a separate map which shows the means of pts across different regions. The shapefile I want to use is from ftp://ftp.epa.gov/wed/ecoregions/cec_na/NA_CEC_Eco_Level2.zip , however, this is a north america map. How can I create the map showing only US based on this north america map? Or is there another better way to do this? thanks so much.
I think that cutting out the non-US data based on the data in the shapefile alone would be hard, since the regions do not correspond to political boundaries - that could be done with rgeos though.
Assuming that "eco" is a SpatialPolygonsDataFrame read in by rgdal::readOGR or maptools::readShapeSpatial, see the available key data for indexing:
sapply(as.data.frame(eco), function(x) if(!is.numeric(x)) unique(x) else NULL)
If you just want to plot it, set up a map with only the US region to start with and then overplot.
library(maps)
map("usa", col = "transparent")
We see that the data is in Lambert Azimuthal Equal Area:
proj4string(eco)
[1] " +proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"
So
require(rgdal)
eco.laea <- spTransform(eco, CRS("+proj=longlat +ellpse=WGS84"))
plot(eco.laea, add = TRUE)
If you want to plot in the original Lambert Azimuthal Equal Area you'll need to get the bounding box in that projection and start the plot based on that, I just used existing data to make an easy example. I'm pretty sure the data could also be cropped with rgeos against another boundary too, but depends what you actually want.

Resources