I aim to combine biodiversity data with land cover information (rasters and vectors).
However, I need to match the resolution, extent, CRS, and dimensions of each raster (predictor variables) with my biodiversity data (answer variables). I had succeed to do it individually but there are six rasters.
Although, when I try a loop for the raster stack. I got some errors.
library(terra)
library(raster)
#Create a raster stack with land cover predictors:
CDI_stack<-raster::stack(list.files(path = dir_Proj1, pattern='.tif', full.names=T))
#Convert to cylindrical equal area projection
equalareaproj<-"+proj=cea +lon_0=0 +lat_ts=30 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"
crs(CDI_stack, warn=FALSE)<-equalareaproj
#Raster with standard dimension, resolution, extention and CRS
standard<-terra::subset(study_area, 2)
#Loop for the raster stack
for(i in 1:length(CDI_stack#layers)){
#Creating a single raster with each layer to maintain values
CDI_layer<-terra::rast(terra::subset(CDI_stack, i))
#Matching a raster extention individually
CDI_layer<-ext(standard)
#Cropping it with standard raster to reduce matching error
raster::crop(CDI_layer[i],standard)
#Resample resolution
terra::resample(CDI_layer[i], standard, method= "near", threads= T)
#Write the raster:
return(writeRaster(Resampled_layer,
filename=paste0("~/Land use/Chronic_Anthropogenic_Disturbance_Surface/", CDI_layer[i]),
format="GTiff", overwrite=TRUE))
}
I found these errors:
Error in h(simpleError(msg, call)) :
error evaluating argument 'x' in method selection for function 'crop': 'this S4 class is not subsettable
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘crop’ for signature ‘"numeric"’
I would like to know if there's any complication to use raster stack or whether I am doing any code step wrongly. I expect to found the correction on the code or of the use of class object.
Please, I hope for your support. Thank you!
G.
Thank you for your advice, Mr. Hijimans.
I found too many errors.
When we do it directly with the raster stack the R returns that the method for the function 'resample' does not work on RasterStack class (see below).
As a stack can have multiple layers, the loop simplified the process rather to work on each one of them.
I preferred to work with a list from the raster stack than the stack, it worked better in the loop.
Also, I used a vector to crop the raster, it preserved raster values (avoiding return NA).
rc <- terra::resample(CDI_stack, standard, method= "bilinear", threads= T)
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘resample’ for signature ‘"RasterStack", "SpatRaster"’
#Create a list from the stack with land cover predictors:
CDI_list<-terra::as.list(CDI_stack)
rm(study_area,CDI_stack)
#Create a list to store the results
results <- list()
#Loop for each SpatRaster from the list
for(i in 1:length(CDI_list)) {
r<-rast(CDI_list[[i]]) # create a raster for each layer
ext(r) <-ext(standard) # redefine extension for each layer
#Crop rasters using the vector to avoid 'NA' values
rc <- terra::crop(r, standard_vec)
#Resample rasters following standard parameters
rc <- terra::resample(rc, standard, method= "bilinear", threads= T)
#Rewrite the list layers with the result
results[[i]] <- rc
}
#Check the values
results[[4]]
#Rasterize the list to save it as a data frame
resampled<-rast(results)
df<-as.data.frame(resampled)
summary(df)
#Save the data frame in the project directory
data.table::fwrite(df, "~/Land use/DATASETS/resampled.csv")
It should be easy enough to find out what is going wrong when you run the code line by line; including inside the for-loop (set i to 1 or whatever the valye is when the error occurs).
You will see that this fails:
CDI_layer <- ext(standard)
raster::crop(CDI_layer[i],standard)
Because CDI_layer[i] is a single number.
There are other things that are awkward. Especially, just use "terra", do not also use "raster" at the same time to avoid confusion.
Seeing your answer it would seem that you can do all of this in two lines
CDI_stack <- terra::rast(files)
rc <- terra::resample(CDI_stack, standard, method= "bilinear", threads= T)
df <- as.data.frame(rc)
Related
I have this, and I am trying to use gDistance to calculate the distance between each centroid and the city of Baghdad. I am trying to do it like this:
gDistance(districts_centroids, districts#data$ADM3NAME %in% c("Baghdad"), byid=TRUE)
Where district_centroids are Formal Class SpatialPoints, and the districts#data... is basically the city of Baghdad in the shp file.
I get an error saying the following:
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘is.projected’ for signature ‘"logical"’
In addition: Warning message:
In RGEOSDistanceFunc(spgeom1, spgeom2, byid, "rgeos_distance") :
Spatial object 1 is not projected; GEOS expects planar coordinates
I am completely new to R and I don't really know what's going on.
Any help would be appreciated
Thank you!
This is a great question. After taking a look at things, it was decided the best way to answer this question was using simple feature objects rather than spatial objects.
The map in question looks familiar. I used the IRQ_2_sf.rds map which is probably the same map used and shown above. There are other alternative ways to achieve the solution to this question. Jupyter Lab is the IDE used.
Using the Google API and the geocode function, the coordinates for Baghdad were retrieved.
baghdad <- geocode("Baghdad, Iraq", source = c("google") )
A tibble: 1 × 2
lon lat
<dbl> <dbl>
44.36607 33.31524
Then sf functions were used to create the sf column object.
baghdad.sfg <- st_point(c(lon, lat), dim = "XY")
baghdad.sfc <- st_sfc(baghdad.sfg, crs = 4326)
Then, using the sf map named iraq, the centroids were created.
Note: warning message - st_centroid does not give correct centroids for longitude/latitude data. For this answer, the centroids will be close
enough.
iraq.c <- st_centroid(iraq)
The distance from each centroid to Baghdad gets determined in kilometers.
head(dist <- data.frame(c(st_distance(iraq.c$geom[], baghdad.sfc)/1000)))
Units: [m]
[1] 28.63250 59.61553 215.43354 323.06418 259.14509 113.55356
And then create a date frame that includes the names, the centroid geometry and the distance values. Requires some cleaning and binding.
distance <- c(dist$c.st_distance.iraq.c.geom....baghdad.sfc..1000.)
x <- distance[]
d_Bdad_Km <- as.numeric(str_extract(x, "[0-9]*.[0-9]."))
iraq2 <- iraq[-c(5, 8,9,10,11,12,13)]
df_dist <- cbind(iraq2, d_Bdad_Km) # df as desired
And then the outputs gets plotted.
plot(iraq$geom)
plot(iraq.c$geom, add = TRUE, col = "red")
plot(baghdad.sfc, add = TRUE, pch = 19, col = "blue")
Please ask if there are any follow-up questions. The plot can be viewed at this link:
I always get error to this
# polygon that to be window
neighborhoods <- st_read("neighborhoods/neighborhoods.shp")
# convert CRS to planar projection as recommended by (https://stackoverflow.com/questions/59597078/use-sf-polygon-object-as-window-in-spatstat)
neighborhoods_3857 <- st_transform(neighborhoods, crs = 3857)
# point that to be PPP spatstat
trees <- st_read("trees/trees.shp")
# convert to planar projection
trees_3857 <- st_transform(trees, crs = 3857)
The problems, the "trees_3857" doesn't have dataframe columns that represent in EPSG3857 coordinates, so Feature column of "trees_3857" doesn't have x and y columns that respect to EPSG 3857
q <- ppp(x=?, y=?, win=neighborhoods_3857)
what I have done but error
z <- as.ppp(trees_3857, win=neighborhoods_3857)
Error in as.ppp.sf(trees_3857, win = neighborhoods_3857): unused argument (win = neighborhoods_3857)
Traceback:
You can get the data freely from datacamp.
https://assets.datacamp.com/production/repositories/738/datasets/96a72364e69d872645038b3a6dc7c0dbcb1114d6/neighborhoods.zip
https://assets.datacamp.com/production/repositories/738/datasets/08a3684dc4d538d59ba051a64a834166883ab5d1/trees.zip
Although you're wanting to transform your data into an object of class "ppp" from the spatstat package, the error message indicates that the problem originated in the function as.ppp.sf which is part of the sf package.
The error message says unused argument: win which means that the function did not recognise or accept the argument win.
Just to make it more challenging, the function as.ppp.sf is not documented and is not visible... By typing sf:::as.ppp.sf we can see the function body and figure out that the function has only one argument, so it does not accept any window information.
This is not the way the generic function as.ppp is designed to work in the spatstat package, so if you looked for help(as.ppp) in spatstat, it's not surprising that you got confused.
The best solution is (as Ege Rubak suggests) to convert the point coordinates and then add the window information:
z <- as.ppp(trees_3857)
Window(z) <- as.owin(neighborhoods_3857)
The conversions as.ppp and as.owin will be executed using code in sf so I can't guarantee they will work. The assignment Window(z) <- will be executed in spatstat code, see help("Window<-.ppp").
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.
I'm working with satellite tracked animals and have a load of relocation data.
So I have my map data and relocations as SpatialPointsDataFrames and when I ask
if proj4string(map)==proj4string(locs) I get TRUE.
But when I try the count.points function as follows
cp <- count.points(locs, map)
I get the following error
Error in count.points(SpatialPoints(x), w) :
different proj4string in w and xy
Does anyone have any ideas on why this is the case?
Edit Code:
load("mydata")
map = mydata$map
map
mimage(map)
locs= mydata$relocs
locs
image(map)
points(locs, col=as.numeric(slot(locs, "data")[,1]), pch=16)
cp <- count.points(locs, map)
Reproducible example would go a long, long way here. But generally speaking R's comparison of projection strings is approximately verbatim. So if there's an extra space or so forth, it will fail.
Given the out for proj4string(map), proj4string(locs), proj4string(SpatialPoints(locs)) in the comment, particularly that proj4string(SpatialPoints(locs)) is NA, I'd say that count.points is dropping the proj4string when it changes to a SpatialPoints object. I think the way to coerce a SPDF to SP while keeping the projection string is via as(x,"SpatialPoints").... Try using trace to insert that into count.points?
I would like to merge some regions in gadm data and then plot the map. So far I have the following:
#install.packages("sp",dependencies=TRUE)
#install.packages("RColorBrewer",dependencies=TRUE)
#install.packages("maptools",dependencies=TRUE)
library(sp)
library(maptools)
#library(RColorBrewer)
# get spatial data
con <- url("http://gadm.org/data/rda/CZE_adm2.RData")
print(load(con))
close(con)
IDs <- gadm$ID_2
IDs[IDs %in% c(11500:11521)] <- "11500"
gadm_new <- unionSpatialPolygons(gadm, IDs)
# plot map
spplot(gadm_new, "NAME_2", col.regions=col, main="Test",colorkey = FALSE, lwd=.4, col="white")
However this results in error:
Error in function (classes, fdef, mtable) :
unable to find an inherited method for function "spplot", for signature "SpatialPolygons"
Now I have no idea what can possibly fix this error.
I'm not sure about what you're trying to do here.
The error is due to the fact that spplot is used to draw spatial objects with attributes, ie with associated data. Your gadm object is of class SpatialPolygonsDataFrame, so it defines polygons and associated data that can be accessed via the slot gadm#data. When you use UnionSpatialPolygons, you only get a SpatialPolygons class object, which can be plotted with plot, but not with spplot :
IDs <- gadm$ID_2
IDs[IDs %in% c(11500:11521)] <- "11500"
gadm_new <- unionSpatialPolygons(gadm, IDs)
plot(gadm_new)
If you want to use spplot, you have to merge your associated data manually, the same way you merged your polygons, and then build back a SpatialPolygonsDataFrame. One way to do it is the following :
gadm_new <- gadm
## Change IDs
gadm_new$ID_2[gadm_new$ID_2 %in% c(11500:11521)] <- "11500"
## Merge Polygons
gadm_new.sp <- unionSpatialPolygons(gadm_new, gadm_new$ID_2)
## Merge data
gadm_new.data <- unique(gadm_new#data[,c("ID_2", "ENGTYPE_2")])
## Rownames of the associated data frame must be the same as polygons IDs
rownames(gadm_new.data) <- gadm_new.data$ID_2
## Build the new SpatialPolygonsDataFrame
gadm_new <- SpatialPolygonsDataFrame(gadm_new.sp, gadm_new.data)
Then you can use spplot to plot a map with an associated attribute :
spplot(gadm_new, "ENGTYPE_2", main="Test", lwd=.4, col="white")
Note that here I only used the ENGTYPE_2 variable of your data, not the NAME_2 variable, as I don't see the point to represent a variable where each value seems unique for each polygon.