Joining seperate SpatialPolygons within a list in R - r

This is an example of a list with two separate (not adjacent or overlapping) SpatialPolygons and I would like to join them into one shapefile. For some reason no matter what I try I keep getting an error:
library(sp)
coords = matrix(c(78.46801, 19.53407,
78.46801, 19.74557,
78.83157, 19.74557,
78.83157, 19.53407,
78.46801, 19.53407),
ncol = 2, byrow = TRUE)
P1 = Polygon(coords)
Ps1 = SpatialPolygons(list(Polygons(list(P1), ID = "a")), proj4string=CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"))
coords2 = matrix(c(77.46801, 17.53407,
77.46801, 17.74557,
77.83157, 17.74557,
77.83157, 17.53407,
77.46801, 17.53407),
ncol = 2, byrow = TRUE)
P2 = Polygon(coords2)
Ps2 = SpatialPolygons(list(Polygons(list(P2), ID = "a")), proj4string=CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"))
P_list <- list(Ps1,Ps2)
joined = SpatialPolygons(lapply(P_list, function(x){x#polygons[[1]]}))
Error in validObject(res) :
invalid class “SpatialPolygons” object: non-unique Polygons ID slot values

Related

How can remove wrapline while buffering with sf package in r

How can I remove the crossing line while using the buffer code below. I tried to create buffers round some point locations and to have a union but ended up getting a crossline.
please see the codes below
train_data
library(raster)
library(dismo)
library(sf)
bioc1 <- getData('worldclim', var='bio', res=5) #
bio1 <- bioc1[[1]]
plot(bio1)
train <- read.csv("forexample_training.csv") # the points locations to be buffered
head(train)
train.sf <- sf::st_as_sf(train, coords=c("longitude", "latitude"), crs=raster::crs(bio1))
plot(train.sf, add=TRUE)
eckertIV <- "+proj=eck4 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"
train.sf <- sf::st_transform(train.sf, crs = eckertIV)
train.buf <- sf::st_buffer(train.sf, dist = 500000) %>%
sf::st_union() %>%
sf::st_sf() %>%
sf::st_transform(crs = raster::crs(bio1))
plot(bio1, main = names(bio1))
train.sf <- sf::st_as_sf(train, coords=c("longitude", "latitude"), crs=raster::crs(bio1))
plot(train.sf, add=TRUE)
# To add sf objects to a plot, use add = TRUE
plot(train.buf, border = "red", lwd = 3, add = TRUE)

Removing density (polygon )outside country map boundary in R

I have a location point data (lat and long) like this to map and I want to remove density lines outside the US map boundary.
df1<-structure(list(Latitude = c(44.085655, 45.75582402, 44.465059,
46.85455171, 44.79125494, 44.085655, 44.43086558, 45.75582402,
44.77051274, 45.19945455, 47.27561322, 44.21957345, 44.3090238,
44.94220871, 44.961121, 44.710093, 44.34052462, 45.11789419,
45.95867596, 46.56683647, 46.50792317, 44.45755466, 45.07106473,
44.28764499, 45.77015307, 44.71947041, 45.00157585, 44.68872029,
44.533648, 46.88808589, 44.56185674, 44.08025478, 45.36716924,
44.82353463, 45.06309272, 46.14316994, 44.47153, 44.29015112,
44.3461, 44.3429524167217, 44.3622947358144, 46.861376854859,
46.193502, 44.28649439, 44.677071, 44.656418), Longitude = c(-70.164692,
-87.08797801, -73.1317265, -68.03996219, -68.80975286, -70.164692,
-71.18455899, -87.08797801, -85.64676572, -67.27073026, -68.58126288,
-73.50262934, -71.75870552, -72.17091902, -74.82915083, -73.447775,
-74.12240542, -87.60659852, -86.22085006, -87.408152, -84.3395823,
-83.33775439, -83.42056958, -85.39666393, -84.72208165, -84.69989941,
-84.66704973, -85.64621272, -87.933788, -67.99941449, -70.54746671,
-70.18023411, -68.53049377, -68.73114004, -69.87230606, -67.83254698,
-73.20752, -69.69422198, -69.7603999999998, -69.7510695984823,
-69.8046068622161, -68.0330276970697, -67.801417, -69.6878877839999,
-67.57706, -67.646081)), row.names = c(NA, -46L), class = "data.frame")
I am mapping this data with this code:
world <- ne_countries(scale = "medium", returnclass = "sf")
usa = filter(world,admin =="United States of America")
usa <- st_as_sf(maps::map("state", fill=TRUE, plot =FALSE))
# Plot
ggplot() +
geom_sf(data = usa, fill = "blue",color = "black",alpha=.9) +
coord_sf(
xlim = c(-119, -74),
ylim = c(22, 51),
default_crs = sf::st_crs(4326),
crs = st_crs("ESRI:102003"),
expand = TRUE,
lims_method = "box",
label_axes = list(
bottom = "E", top = "E",
left = "N", right = "N"
))+stat_density2d_filled(data = df1, aes(x = Longitude, y = Latitude, fill=(..level..),
alpha = (..level..)), geom = "polygon")
The plot is like that
I am looking to remove the polygons are outside the US map (Blue texture). I have used this code to do that but In step 2 I have problem :
#Step 1
spdf <- SpatialPointsDataFrame(coords = vetrace1[, c("Longitude", "Latitude")], data = vetrace1,
proj4string = CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))
step 2
whatever <- spdf[!is.na(over(spdf, as(usa, "SpatialPolygons"))), ]
# step 3
whatever <- as.data.frame(whatever)
The error I got is :
"Error in h(simpleError(msg, call)) :
error in evaluating the argument 'y' in selecting a method for function 'over': no method or default for coercing “sf” to “SpatialPolygons”"
Could you help me how to trim this map.

Replacing "rdgal" with a Data Frame in R?

I found this R code (Search button for Leaflet R map?) and was able to make a interactive map in R:
library(inlmisc)
city <- rgdal::readOGR(system.file("extdata/city.geojson",
package = "inlmisc")[1])
opt <- leaflet::markerClusterOptions(showCoverageOnHover = FALSE)
map <- CreateWebMap("Topo")
map <- leaflet::addMarkers(map, label = ~name, popup = ~name,
clusterOptions = opt,
clusterId = "cluster",
group = "marker", data = city)
map <- AddHomeButton(map)
map <- AddClusterButton(map, clusterId = "cluster")
map <- AddSearchButton(map, group = "marker", zoom = 15,
textPlaceholder = "Search city names...")
map
I was curious and wanted to see the format and entries of the "city" file. I was expecting this file to be a "tabular" file (i.e. containing rows and columns, like a data frame), but when I opened the file, it did not appear in this format at all - this file is apparently a "SpatialPointsDataFrame":
> head(city)
class : SpatialPointsDataFrame
features : 6
extent : -123.09, -73.8, 31.58, 44.62 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
variables : 2
names : name, capital
min values : Abilene TX, 0
max values : Albany OR, 2
I then found this post here (How to convert a spatial dataframe back to normal dataframe?) and saw that you can convert a SpatialPointsDataFrame into a regular data frame like this:
DF <- as.data.frame(city)
> head(DF)
name capital coords.x1 coords.x2
1 Abilene TX 0 -99.74 32.45
2 Akron OH 0 -81.52 41.08
3 Alameda CA 0 -122.26 37.77
4 Albany GA 0 -84.18 31.58
5 Albany NY 2 -73.80 42.67
6 Albany OR 0 -123.09 44.62
But is there a way to convert a regular data frame into a "SpatialDataFrame"? I tried the following code and then tried to plot the results:
#https://stackoverflow.com/questions/29736577/how-to-convert-data-frame-to-spatial-coordinates
library(sf)
city <- st_as_sf(x = DF,
coords = c("coords.x1", "coords.x2"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
map <- CreateWebMap("Topo")
map <- leaflet::addMarkers(map, label = ~name, popup = ~name,
clusterOptions = opt,
clusterId = "cluster",
group = "marker", data = city)
map <- AddHomeButton(map)
map <- AddClusterButton(map, clusterId = "cluster")
map <- AddSearchButton(map, group = "marker", zoom = 15,
textPlaceholder = "Search city names...")
map
The code ran, but I get this warning message:
Warning message:
sf layer has inconsistent datum (+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs).
Need '+proj=longlat +datum=WGS84
Am I doing this correctly?
Thank you!
Leaflet uses a slightly different format of crs than sf with st_as_sf, which you can read more about on GitHub. You have a few options, where first we could use a shortened crs, like here:
library(sf)
city <- st_as_sf(x = DF,
coords = c("coords.x1", "coords.x2"),
crs = "+proj=longlat +datum=WGS84 +no_defs")
Or you can use sp::CRS along with your crs definition, so that it is properly read by leaflet:
city <- st_as_sf(x = DF,
coords = c("coords.x1", "coords.x2"),
crs = sp::CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"))
Or another option would be to use the SRID 4326 as the crs (which will set the Geodetic CRS):
city <- st_as_sf(x = DF,
coords = c("coords.x1", "coords.x2"),
crs = 4326)
map <- CreateWebMap("Topo")
map <- leaflet::addMarkers(map, label = ~name, popup = ~name,
clusterOptions = opt,
clusterId = "cluster",
group = "marker", data = city)
map <- AddHomeButton(map)
map <- AddClusterButton(map, clusterId = "cluster")
map <- AddSearchButton(map, group = "marker", zoom = 15,
textPlaceholder = "Search city names...")
map
You will notice that in the answer you are using that they are using mapview, which does work with the format that you give (i.e., crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"). So, it would work with your code, but it won't be in the leaflet style:
city <- st_as_sf(x = DF,
coords = c("coords.x1", "coords.x2"),
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
mapview::mapview(city)

Overlaying (plotting) point data on raster layer

So I have the following script trying to prepare the data to do modelling on them later on using "biomod2" package. It tries to overlay species (xlm) presence points on environmental layers (bio1, bio7).
library(biomod2)
library(raster)
data <- structure(list(longitude = c(-122.84,-119.418,-78.6569,-78.1834, -89.3985), latitude = c(45.28,36.7783,37.4316,-1.8312, 32.3547)), .Names = c("X_WGS84",
"Y_WGS84"), class = "data.frame", row.names = c(NA, -5L))
data$xlm<-1
spdf <- SpatialPointsDataFrame(coords = xy, data = data,
proj4string = CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))
myRespName <- 'xlm'
myResp <- as.numeric(data[,myRespName])
myRespXY <- data[,c('X_WGS84','Y_WGS84')]
myExpl = stack( system.file( "external/bioclim/current/bio3.grd", package="biomod2"),
system.file( "external/bioclim/current/bio4.grd", package="biomod2"))
myBiomodData <- BIOMOD_FormatingData(resp.var = myResp,expl.var = myExpl,resp.xy = myRespXY,resp.name = myRespName)
plot(myBiomodData)
It works in this case, however, the issue is when I want to replace "bio4.grd" and "bio3.grd" layers in the package with my own data, it doesn't work. I have tried it as follow. First i thought it might be "asci" file format but even by converting them to "grd" still I don't get the points overlayed on layers stacked. It does overlay only one point in Southern USA (around Louisiana, Mississippi) though.
library(biomod2)
library(raster)
data <- structure(list(longitude = c(-122.84,-119.418,-78.6569,-78.1834, -89.3985), latitude = c(45.28,36.7783,37.4316,-1.8312, 32.3547)), .Names = c("X_WGS84",
"Y_WGS84"), class = "data.frame", row.names = c(NA, -5L))
data$xylella<-1
spdf <- SpatialPointsDataFrame(coords = xy, data = data,
proj4string = CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))
myRespName <- 'xylella'
myResp <- as.numeric(data[,myRespName])
myRespXY <- data[,c('X_WGS84','Y_WGS84')]
bio2<-raster("C:\\Data\\BioClim_V2_MaxEnt\\wc2.0_bio_10m_02.asc")
crs(bio2) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
writeRaster(bio2, "C:\\Data\\BioClim_V2_MaxEnt\\bio2", overwrite=TRUE)
bio7<-raster("C:\\Data\\BioClim_V2_MaxEnt\\wc2.0_bio_10m_07.asc")
crs(bio7) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
writeRaster(bio7, "C:\\Data\\BioClim_V2_MaxEnt\\bio7", overwrite=TRUE)
myExpl = stack (bio2,bio7)
myBiomodData <- BIOMOD_FormatingData(resp.var = myResp,expl.var = myExpl,resp.xy = myRespXY,resp.name = myRespName)
plot(myBiomodData)
Any help highly appreciated. Many thanks.

How to remove padding added to a PNG image created with writeGDAL

I am using writeGDAL to export raster data in PNG format to use as an image overlay on Google Maps. The image therefore needs to have the correct aspect ratio and must fit the raster extent exactly.
When I export the UTM-projected raster the result is as expected but after I project to the LatLong system the generated PNG has padding right round the raster area.
What do I need to do to get rid of this padding?
Below is sample code which creates 2 images that demonstrate the problem.
library(raster)
library(rgdal)
r <- raster(xmn=742273.5, xmx=742702.5, ymn=6812515.5, ymx=6812995.5, ncols=144, nrows=161)
r <- setValues(r, 1:ncell(r))
projection(r) <- CRS('+proj=utm +zone=35 +south +datum=WGS84 +units=m +no_defs')
pr <- projectRaster(r, crs='+proj=longlat +datum=WGS84 +no_defs')
#Coerce to SpatialPixelsDataFrame and prepare for writeGDAL
rSpdf <- as(r, 'SpatialPixelsDataFrame')
prSpdf <- as(pr, 'SpatialPixelsDataFrame')
rSpdf$colors <- as.numeric(cut(rSpdf$layer, breaks = 255))
prSpdf$colors <- as.numeric(cut(prSpdf$layer, breaks = 255))
colorTable <- list(colorRampPalette(c('red', 'yellow', 'green4'))(256))
#Export in PNG format using writeGDAL
writeGDAL(rSpdf[, 'colors'], 'utm.png', drivername = 'PNG', type = 'Byte', mvFlag = 0, colorTables = colorTable)
writeGDAL(prSpdf[, 'colors'], 'geo.png', drivername = 'PNG', type = 'Byte', mvFlag = 0, colorTables = colorTable)
#Optionally, the rasters can be exported to view in a spatial package (eg SAGA-GIS)
#writeRaster(r, filename='utm.tif', format="GTiff", overwrite=TRUE)
#writeRaster(pr, filename='geo.tif', format="GTiff", overwrite=TRUE)
By converting the projected raster to points and then coercing the points to a SpatialPixelsDataFrame (instead of coercing the raster) the padding is removed.
library(raster)
library(rgdal)
r <- raster(xmn=742273.5, xmx=742702.5, ymn=6812515.5, ymx=6812995.5, ncols=144, nrows=161)
r <- setValues(r, 1:ncell(r))
projection(r) <- CRS('+proj=utm +zone=35 +south +datum=WGS84 +units=m +no_defs')
pr <- projectRaster(r, crs='+proj=longlat +datum=WGS84 +no_defs')
points <- rasterToPoints(pr, spatial = TRUE)
prSpdf <- as(points, 'SpatialPixelsDataFrame')
prSpdf$colors <- as.numeric(cut(prSpdf$layer, breaks = 10))
colorTable <- list(colorRampPalette(c('red', 'yellow', 'green4'))(11))
writeGDAL(prSpdf[, 'colors'], 'geo.png', drivername = 'PNG', type = 'Byte', mvFlag = 0, colorTables = colorTable)

Resources