How can I overlay Sentinal 2 data with shapefiles in R? - r

I need to extract Sentinal 2 data for NDVI for specific study sites. I used RGIS tools and followed the reference manual https://cran.r-project.org/web/packages/RGISTools/RGISTools.pdf . I was able to obtain and plot the time series for NDVI.
Now I have to do the same procedure for my study area. I have a shapefile for my area which is accessible here, https://gis.utah.gov/data/boundaries/zip-codes/. It looks like that the shapefile needs to be converted into raster or sf type object before using it. I used st_as_sf to convert shapefile to sf but I receive the following error in senSearch function,
Error in if (as.integer(json$feed$opensearch:totalResults) > 0) { :
argument is of length zero
It is my first time working with such data, any help is appreciated.

It looks like you try to search using the extent argument. This argument only accepts spatial objects projected as lonlat projections. You can use the region argument with any spatial obj (sp, sf, or raster).
Here you have an example with your region:
library(RGISTools)
library(rgdal)
shp<-readOGR("ZipCodes_shp/ZipCodes")
plot(shp)
senres<-senSearch(startDate = as.Date("2018210", "%Y%j"),
endDate = as.Date("2018215", "%Y%j"),
platform = "Sentinel-2",
region = shp,
product = "S2MSI1C",
username="user",
password="pass")

Related

AdehabitatHR::kernelUD error, geographical CRS given to non-conformant data

I am trying to perform the simple task of estimating a kernel density utilisation distribution across the foraging tracks of all females in my data set (just a visualisation exercise), and have opted for the kernelUD function within the adehabitatHR package in R.
I can set up a simple example of the SpatialPoints object I have been working with, which is formatted in long-lat format.
female <- filter(tracks, Sex == "Female")
# check the range of the longitude and latitude
range(female[,c("Latitude")])
[1] 20.71389 84.20619
range(female[,c("Longitude")])
[1] -23.85262 105.20330
# make the SpatialPoints object
sp.female <- SpatialPoints(coords = female[,c("Longitude", "Latitude")],
proj4string = CRS("+proj=longlat +ellps=WGS84"))
So no points are outside of the expected range for either longitude or latitude, but when I then try and perform the kernelUD:
kd.female <- kernelUD(sp.female, h = "href")
Error in `proj4string<-`(`*tmp*`, value = CRS(pfs1)) :
Geographical CRS given to non-conformant data: -105.076705907
This data point does not appear in the object I am working with, so I am at a loss as to how to troubleshoot the error.
I'm running the following package versions on R v3.6.3
> packageVersion('adehabitatHR')
[1] ‘0.4.19’
> packageVersion('rgdal')
[1] ‘1.5.23’
> packageVersion('sp')
[1] ‘1.4.5’
Thanks in advance for any help.
I have found that transforming to UTM appears to fix the problem, but I would be keen to know why the kernelUD function does not work on data where the coordinates are formatted in classic longitude and latitude.

st_intersection to spatialpolygon dataframe not working

I am trying to get the intersection of two shapefiles (census tracts that fall within the boundaries of certain metropolitan areas). I am able to successfully get the intersecting features, however when I try to convert the output of sf_intersect to a SpatialPolygonsDataframe I get the error:
"Error in as_Spatial(from) : conversion from feature type
sfc_GEOMETRY to sp is not supported"
This is my code:
library(sf)
library(dplyr)
library(tigris)
library(sp)
#download shapefiles corresponding to metro areas
metro_shapefiles<-core_based_statistical_areas(cb = FALSE, year = 2016)
#convert to sf and filter
metro_shapefiles<-st_as_sf(metro_shapefiles)%>%filter(GEOID==31080 )
#Data for California
census_tracts_california<-tracts(state="CA",year=2016)
census_tracts_california<-st_as_sf(census_tracts_california)
#INTERSECT AND CONVERT BACK TO SP
census_tracts_intersected1<-st_intersection(census_tracts_california,
metro_shapefiles)
#back to spatial
census_tracts_intersected1<-as(census_tracts_intersected1,"Spatial")
The error message is telling you you can't convert an sfc_GEOMETRY to a Spatial object. There is no sp equivalent object.
In your intersection result you have a mixture of geometries (and hence, you're returned an sfc_GEOMETRY as your 'geometry'). You can see all the geometries here:
types <- vapply(sf::st_geometry(census_tracts_intersected1), function(x) {
class(x)[2]
}, "")
unique(types)
# [1] "POLYGON" "MULTILINESTRING" "MULTIPOLYGON"
If you want, you can extract each type of geometry, and convert those to SP individually:
lines <- census_tracts_intersected1[ grepl("*LINE", types), ]
polys <- census_tracts_intersected1[ grepl("*POLYGON", types), ]
spLines <- as(lines, "Spatial")
spPolys <- as(polys, "Spatial")
Additional Information
I mentioned in the comments you could use st_join. However, this may not give you the result you want. Within sf library there are the geometric binary predicates, such as ?st_intersects, and geometric operations such as ?st_intersection
The predicates return a sparse (default) or dense matrix telling you with which geometry of y each geometry of x intersects. If you use this within st_join, it will return the (original) geometries that intersect, rather than the sparse matrix.
Whereas the operations (e.g. st_intersection) will compute the intersection, and return new geometries.
Example use
The predicates (st_intersects) can be used inside st_join, and they will return the original geometries which 'intersect'
sf_join <- sf::st_join(census_tracts_california, metro_shapefiles, join = st_intersects)
In this case this gives a single type of object
types <- vapply(sf::st_geometry(sf_join), function(x) {
class(x)[2]
}, "")
unique(types)
# [1] "MULTIPOLYGON"
## so you can convert to a Spatial object
spPoly <- as(sf_join, "Spatial")
But you need to decide if the result of st_intersect is what you're after, or whether you need the new geometries given by st_intersection.
Further reading
information on each join is on the sf blog.
spatial predicates and examples of what the different operations do are on wikipedia (with some good illustrations)
Credit to user #lbussett for their description on the difference between st_intersect and st_intersection
Conversion to a Spatial object can't handle mixed lines and polygons. After the intersection you can extract just the polygons (and discard any lines) using:
st_collection_extract("POLYGON")
Your example doesn't seem to fail anymore, so I've created a new example that intersects two polygons, with a shared side. This results in an intersection output of a polygon and a line.
On the second attempt I've piped the intersection through the st_collection_extract() function prior to successful conversion to a Spatial object.
library(sf)
library(dplyr)
library(sp)
#Create some boxes
BoxA <- st_polygon(list(cbind(c(0,0,2,2,0),c(0,2,2,0,0))))
BoxB <- st_polygon(list(cbind(c(1,1,3,3,1),c(1,3,3,1,1))))
BoxC <- st_polygon(list(cbind(c(2,2,4,4,2),c(0,2,2,0,0))))
#Create a funny shaped union to help demonstrate the intersection issue
BoxAB <- st_union(BoxA,BoxB)
plot(BoxAB)
plot(BoxC,add=TRUE,border="blue")
Example polygons to intersect
#Intersect of BoxAB with BoxC results in a line and a polygon
BoxIntersects<-st_intersection(BoxAB,BoxC)
plot(BoxIntersects)
Intersection made up of a polygon and a line
#back to spatial fails
SpatialVersionOfIntersects<-as(BoxIntersects,"Spatial")
Error in .as_Spatial(from, cast, IDs) :
conversion from feature type sfc_GEOMETRY to sp is not supported
#Intersect again, but this time extract only the polygons
BoxIntersects<-st_intersection(BoxAB,BoxC) %>% st_collection_extract("POLYGON")
#back to spatial suceeds!
SpatialVersionOfIntersects<-as(BoxIntersects,"Spatial")

Dealing with unordered XY points to create a polygon shapefile in R

I've inherited a geodatabase of polygons of lakes for which I am trying to create sampling grids on each lake. My current strategy is to export spatial data to CSV, use R to run a loop to create the grids on each lake, and then write to a new shapefile. However, here is my problem, when exporting to a CSV the WKT strings get messed up and put onto different lines. Okay, no problem, I moved on to exporting just the geometry to CSV so that I get X-Y values. When I simply plot the points they look perfect (using plot(y~x)), but the points are not in order. So, when I transform the data to a SpatialPolygon in the sp package in R using the following sequence:
XY-points -> Polygon -> Polygons -> SpatialPolygon
and then plot the SpatialPolygon I get this:
I know this is an artifact of incorrectly ordered points, because when I order the points by X and then by Y and run the same procedure here is what I get:
This is what the correct plotting is supposed to look like (X-Y data plotted with open circles):
Here is a short reproducible example of what I am trying to deal with:
library(sp)
# correct polygon
data <- data.frame(x=c(1:10, 10:1), y=c(5:1, 1:10, 10:6))
# plot(y~x, data=data)
correct.data.points <- rbind(data, data[1,]) # to close the ring for a polygon
correct.data.coords <- as.matrix(cbind(correct.data.points))
correct.data.poly <- Polygon(correct.data.coords, hole=F)
correct.data.poly <- Polygons(list(correct.data.poly), ID=0)
correct.data.poly.sp <- SpatialPolygons(list(correct.data.poly))
plot(correct.data.poly.sp)
# incorrect polygon
scr.data <- data[c(sample(1:20)),]
# plot(y~x, data=scr.data)
scr.data.points <- rbind(scr.data, scr.data[1,]) # to close the ring for a polygon
scr.data.coords <- as.matrix(cbind(scr.data.points))
scr.data.poly <- Polygon(scr.data.coords, hole=F)
scr.data.poly <- Polygons(list(scr.data.poly), ID=0)
scr.data.poly.sp <- SpatialPolygons(list(scr.data.poly))
plot(scr.data.poly.sp)
Any thoughts? Thanks for any help or insight anyone can provide. Also, for reference I am using QGIS 2.6.0 and the MMQGIS Python plugin to do the geometry exporting.

Converting a raster object to an im object in R

I am trying to convert a raster object to an .im object for use with a point process model in the spatstat package in R. I begin by creating the raster from a tiff file using the raster() package. No problems there. I then proceed by cropping the raster according to a given extent. Again, no problem there. I then specify a spatial window (owin) defined using the same extent. Still no problems. When I then proceed to the final step of converting the raster to the im object using as.im(), the function runs and the new im object is created, but it has somehow lost the pixel information that was contained in the original raster such that each pixel now has the same value in the im object. Any help or suggestions would be most appreciated. Thanks very much.
The date file used is at this link: https://www.dropbox.com/s/n67djm3n0tfa6sx/MGVF_2001_30_arc_sec.tif?dl=0
And the R code is as follows:
library(raster)
library(spatstat)
# First set the geographic extent we'll be using
e <- extent(-20, 60, -40, 35)
# Then read in the Maximum Green Vegetation Fraction tiff and crop it
mgvf <- raster("MGVF_2001_30_arc_sec.tif")
mgvf.2001.africa <- crop(mgvf, e)
# Now let's create a window for in spatstat
SP.win <- as(e, "SpatialPolygons")
W <- as(SP.win, "owin")
# Finally, we create the .im object
mgvf.img <- as.im(X = "mgvf.2001.africa", W = W)
# Notice, there are no errors thrown. However, compare the plots below and see the loss of information:
plot(mgvf.2001.africa)
plot(mgvf.img)
Incidentally, I have tried the above as shown as well as trying to replace the NAs in the raster prior to converting to im. The result is the same. Thanks.

How to block a part of the level plot in R made using lattice package?

I have made a level plot in R of a variable using the lattice package. This grid corresponds to South Asia. I am only interested in viewing the values of this variable (aerosol optical depth) for certain countries in South Asia. I have a dummy variable that takes the value 1 for the countries I am interested in and 0 otherwise. Is it possible for me to colour this part of the grid black or any other colour?
I cannot show the level plot as I am low on reputation with stackoverflow. (The pdf that was attached to the crossposted message to rhelp should now appear:)
Here is my R code:
levelplot(aod ~ longitude + latitude | factor(day), data = aod_Jan,
aspect="iso", contour = TRUE, layout=c(1,1))
Since you are using geographical data, maybe the raster package is useful for you. For example, let's display the altitude of France (download this zip file or use the raster::getData function). After you unzip the file:
library(raster)
fraAlt <- raster('FRA_alt')
plot(fraAlt) ## Not only France is displayed...
If you want to display only the altitude of France, you need the information of the boundaries: download this RData file (or use the raster::getData function). This RData contains a SpatialPolygonsDataFrame (named gadm) which can be converted to a Raster with:
mk <- rasterize(gadm, fraAlt)
Now you can mask the altitude raster with the boundaries:
fraAltMask <- mask(fraAlt, x)
plot(fraAltMask) ##Now only France is displayed
Finally, if you want to use lattice methods you need the rasterVis package:
library(rasterVis)
levelplot(fraAlt)
levelplot(fraAltMask)
Now, all together with the boundaries superimposed:
s <- stack(fraAlt, fraAltMask)
layerNames(s) <- c('Alt', 'AltMask')
boundaries <- as(gadm, 'SpatialLines')
levelplot(s) + layer(sp.lines(boundaries))
Use the subset argument to levelplot. Perhaps:
levelplot(aod ~ longitude + latitude | factor(day), data = aod_Jan, subset = dummy==1,
aspect="iso", contour = TRUE, layout=c(1,1))

Resources