I am writing a script that will take any three rasters, and crop them to the minimum possible extent. All three rasters will have the same resolution and projection. However, cropping to the minimum extent does not change the extents for the three rasters. I've tried setExtent and the same thing happens. If anyone can give suggestions I would really appreciate it. Here is sample code:
library(raster)
#Projection of all three rasters
newproj<- "+proj=utm +zone=4 +datum=WGS84 +units=m +no_defs +ellps=WGS84
+towgs84=0,0,0"
#Create three rasters with varying extents
raster1p<- raster(crs = newproj)
extent(raster1p)<- c(531247, 691847, 7856684, 7987884)
res(raster1p)<- c(100, 100)
values(raster1p)<- NA
raster2p<- raster(crs = newproj)
extent(raster2p)<- c(533550.8, 646550.8, 7881307, 7973807)
res(raster2p)<- c(100, 100)
values(raster2p)<- NA
raster3p<- raster(crs = newproj)
extent(raster3p)<- c(525739, 689839, 7857305, 7996505)
res(raster3p)<- c(100, 100)
values(raster3p)<- NA
#Find minimum extent
xmin1<- c(xmin(extent(raster1p)), xmin(extent(raster2p)), xmin(extent(raster3p)))
xmax1<- c(xmax(extent(raster1p)), xmax(extent(raster2p)), xmax(extent(raster3p)))
ymin1<- c(ymin(extent(raster1p)), ymin(extent(raster2p)), ymin(extent(raster3p)))
ymax1<- c(ymax(extent(raster1p)), ymax(extent(raster2p)), ymax(extent(raster3p)))
xmin_new<- min(xmin1)
xmax_new<- min(xmax1)
ymin_new<- min(ymin1)
ymax_new<- min(ymax1)
newextent=c(xmin_new, xmax_new, ymin_new, ymax_new)
#Crop rasters to minimum extent
crop(raster1p, newextent)
crop(raster2p, newextent)
crop(raster3p, newextent)
#Compare extents
extent_check<- c(extent(raster1p), extent(raster2p), extent(raster3p))
However, when I look at the extent_check to see if the extents now match, I see that the extents have not changed at all:
> extent_check
[[1]]
class : Extent
xmin : 531247
xmax : 691847
ymin : 7856684
ymax : 7987884
[[2]]
class : Extent
xmin : 533550.8
xmax : 646550.8
ymin : 7881307
ymax : 7973807
[[3]]
class : Extent
xmin : 525739
xmax : 689839
ymin : 7857305
ymax : 7996505
Any idea what I could be doing wrong? Thank you for your time
I think it is not so much about doing something wrong, but rater a misconception (although there is a mistake in your code).
Example data
library(raster)
prj <- "+proj=utm +zone=4 +datum=WGS84"
r1 <- raster(res=100, ext=extent(c(531247, 691847, 7856684, 7987884)), crs=prj, vals=NA)
r2 <- raster(res=100, ext=extent(c(533550.8, 646550.8, 7881307, 7973807)), crs=prj, vals=NA)
r3 <- raster(res=100, ext=extent(c(525739, 689839, 7857305, 7996505)), crs=prj, vals=NA)
Find the "minimum extent"
e <- intersect(intersect(extent(r1), extent(r2)), extent(r3))
Note that the result is different from yours because you use
xmin_new <- min(xmin1) and ymin_new <- min(ymin1)
Where it should be
xmin_new <- max(xmin1) and ymin_new <- max(ymin1)
Now crop
r1e <- crop(r1, e)
r2e <- crop(r2, e)
r3e <- crop(r3, e)
Inspect the resulting extents
t(sapply(c(r1e, r2e, r3e), function(i) as.vector(extent(i))))
# [,1] [,2] [,3] [,4]
#[1,] 533547.0 646547.0 7881284 7973784
#[2,] 533550.8 646550.8 7881307 7973807
#[3,] 533539.0 646539.0 7881305 7973805
They are not exactly the same, because that is not possible because the rasters do not align. Their "origins" are different
t(sapply(c(r1e, r2e, r3e), origin))
# [,1] [,2]
#[1,] 47.0 -16
#[2,] -49.2 7
#[3,] 39.0 5
To make them align, you would need to do something like this
r1e <- crop(r1, e)
r2e <- resample(r2, r1e)
r3e <- resample(r3, r1e)
t(sapply(c(r1e, r2e, r3e), function(i) as.vector(extent(i))))
# [,1] [,2] [,3] [,4]
#[1,] 533547 646547 7881284 7973784
#[2,] 533547 646547 7881284 7973784
#[3,] 533547 646547 7881284 7973784
Related
Does anybody know if there is a built-in function in R terra to generate a SpatVector polygon from an ext object, please?
library(terra)
# A SpatExtent object
ext1 <- ext(c(-74.5, -72.5, 9.5, 12.0))
How I manually created the coordinates of the polygon vertices
box_coords <- rbind(
c(ext1[1], ext1[3]),
c(ext1[2], ext1[3]),
c(ext1[2], ext1[4]),
c(ext1[1], ext1[4]),
c(ext1[1], ext1[3])
)
box_coords
# [,1] [,2]
#[1,] -74.5 9.5
#[2,] -72.5 9.5
#[3,] -72.5 12.0
#[4,] -74.5 12.0
#[5,] -74.5 9.5
How I convert the coordinate into a SpatVector
box1 <- vect(box_coords, type = "lines")
The way I'd like it to be, but that doesn't work
box1 <- vect(ext1)
You can use as.polygons
library(terra)
e <- ext(-74.5, -72.5, 9.5, 12.0)
p <- as.polygons(e, crs="")
# or
p <- as.polygons(e, crs="+proj=longlat")
You can also use as.points and as.lines
To get a polygon for the extent of SpatRaster or SpatVector x you can do
x <- rast()
p <- as.polygons(x, extent=TRUE)
The latter has the advantage that the coordinate reference system is not lost, or is less convulted than the alternative
p <- as.polygons(ext(x), extent=TRUE, crs=crs(x))
I have now added this path as well (terra 1.7-6) .
ve <- vect(e, crs="+proj=longlat")
And, to get a numeric vector (not a SpatVector) you can do
as.vector(e)
I need to estimate the weighted average of raster values for the polygon shown in squares. I want to obtain raster value and its weight within each square in the polygon shape. (As shown in this post: How can I extract an area weighted sum from a raster into a polygon in R?)
But, please see my code below and the image of what I am getting as weights. Can somebody correct me what I am doing wrong here and why my output is different from as shown in the above post.? I want to obtain an output like in the post above. Seems likes the weights I am getting is wrong too.
Please see the attached input data set here:
https://bft.usu.edu/w8crs
Thanks.
library(raster)
library(sp)
library(rgdal)
library(rgeos)
rlist = list.files(getwd(), pattern = "tif$", full.names = TRUE)
inshp = "Test"
rdata <- rlist[1]
r <- raster(rdata)
sdata <- readOGR(dsn=getwd(), layer=inshp)
sdata <- spTransform(sdata, crs(r))
extract(r, sdata, weights=TRUE)
Output:
[[1]]
value weight
56.75139 1
[[2]]
value weight
61.18781 1
[[3]]
value weight
56.75139 1
[[4]]
value weight
61.18781 1
Here is a reproducible example
library(raster)
packageVersion("raster")
#[1] ‘2.8.4’
r <- raster(xmn=0, xmx=1, ymn=0, ymx=1, nrow=2, ncol=2)
values(r) <- 1:4
m <- matrix(c(0.4, 0.6, 0.8, 0.6, 0.7, 0.2, 0.3, 0.2), ncol=2, byrow=TRUE)
s <- spPolygons(m)
plot(r); lines(s)
extract(r, s, weights=TRUE)
#[[1]]
# value weight
#[1,] 1 0.0625
#[2,] 2 0.1875
#[3,] 3 0.3125
#[4,] 4 0.4375
This did not work for you, because your polygon was very small relative to the raster cell size. I have changed the function, such that it increases the precision for those cases. I now get this with your data:
> extract(r, sdata, weights=TRUE)
[[1]]
value weight
56.75139 1
[[2]]
value weight
[1,] 61.18781 0.6592593
[2,] 56.75139 0.3407407
[[3]]
value weight
56.75139 1
[[4]]
value weight
[1,] 61.18781 0.5522388
[2,] 56.75139 0.4477612
To make it reproducible without downloads, for one of your polygons:
library(raster)
r <- raster(ncol=2, nrow=1, xmn=596959.624056728, xmx=624633.120455544, ymn=568805.230192675, ymx=582641.978392083, crs='+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=37.5 +lon_0=-96 +x_0=0 +y_0=0 +datum=NAD83 +units=m')
values(r) <- c(61.18781, 56.75139)
g <- data.frame(matrix(c(rep(1, 18), rep(0,6), 611318.079488842,611440.751254539,610712.115334383,609842.749239201, 609703.303842618,611318.079488842,581038.816616668,579434.971927127, 579381.167042005,579315.223934334,580917.724282178,581038.816616668), ncol=6))
colnames(g) <- c('object','part','cump','hole','x','y')
p <- as(g, "SpatialPolygons")
crs(p) <- crs(r)
extract(r, p, weights=TRUE)
#[[1]]
# value weight
#[1,] 61.18781 0.6592593
#[2,] 56.75139 0.3407407
I'm trying to follow the code to construct a residual autocovariate model described here: https://github.com/jejoenje/PubsRexamples/blob/master/Crase_etal.R#L16
After creating a large raster space I get an error when assigning values to the raster. I have 1000 random points to sign to the raster so there are many points without data (NA). Any ideas?
head(xy)
[,1] [,2]
[1,] 543510.0 6968620
[2,] 543570.0 6968620
[3,] 543570.0 6968560
[4,] 543599.9 6968560
[5,] 543510.0 6968530
[6,] 543389.9 6968470
head(xy_residuals)
[,1] [,2] [,3]
1 543510.0 6968620 -0.4257671
2 543570.0 6968620 -0.4541684
3 543570.0 6968560 -0.4310492
4 543599.9 6968560 -0.4649595
5 543510.0 6968530 -0.5506348
6 543389.9 6968470 -0.4928708
summary(xy)
X Y
Min. :538800 Min. :6931480
1st Qu.:540480 1st Qu.:6932860
Median :541350 Median :6935320
Mean :541529 Mean :6943218
3rd Qu.:542670 3rd Qu.:6954003
Max. :544290 Max. :6968620
# Define raster ymn, ymx, xmn and xmx from coordinates
# ncol=xmx-xmn nrow=ymx-ymn.
rast <- raster(ncol = 5490, nrow = 37140, ymn = 6931480, ymx = 6968620,
xmn = 538800, xmx = 544290)
rast
class : RasterLayer
dimensions : 37140, 5490, 203898600 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 538800, 544290, 6931480, 6968620 (xmin, xmax, ymin, ymax)
coord. ref. : NA
Problematic call:
rast[cellFromXY(rast, xy)] <- xy_residuals[, 3]
Error in .replace(x, i = i, value = value, recycle = 1) :
cannot replace values in large Raster objects if their length is not 1 or the number of cells to be replaced**
The error message says why this happens (But perhaps this "feature" needs some improvement.) The raster is very large and may not fit in memory (RAM). That may be too conservative an assessment . You can adjust that via rasterOptions or you can try:
library(raster)
r <- raster(ncol = 10, nrow = 10, ymn = 6931480, ymx = 6968620, xmn = 538800, xmx = 544290)
m <- matrix(c(539868,542002,542409,6945031,6940012,6935997, 1, 2, 3), 3, 3)
cells <- cellFromXY(r, m[,1:2])
# create a large vector with all cells
v <- rep(NA, ncell(r))
v[cells] <- m[,3]
v <- setValues(r, v)
If that does not work, you could look at update, but that is more risky as it overwrites data on file, but that should not be a concern in this case.
r <- setValues(r, NA)
# that probably creates a file on disk. If not do
# r <- writeRaster(r, filename='test.grd')
r <- update(r, cell=cells, v=m[,3])
I got a raster layer 'w_wgs' of climatic values. On the other side, I created an empty raster 'grid'.
I want to assign the values stored in 'w_wgs' into my empty raster grid. I tried merge(), overlay(), over() but these don't work.
How can I do this ? assuming these two rasters don't have the same extent nor resolution (nor equal number of cells, obviously)...but both have the same CRS (WGS84).
Here, a description of my 2 objects :
> extent(w_wgs)
class : Extent
xmin : -64.50344
xmax : 74.07016
ymin : 12.93039
ymax : 72.72534
> res(w_wgs)
[1] 0.01320 0.00895
> res(grid)
[1] 0.08 0.08
> extent(grid)
class : Extent
xmin : 5
xmax : 17.96
ymin : 40
ymax : 50
I think you need to use resample
grid <- resample(w_wgs, grid)
A small example that should be similar to your case:
x <- matrix(1:100, nr = 10, nc = 10)
a <- raster(x)
x2 <- matrix(NA, nr = 3, nc = 3)
b <- raster(x2)
# Manually changing the extent and resolution of b
b#extent#xmax <- 0.5
b#extent#ymin <- 0.3
b <- resample(a, b)
par(mfrow = c(2, 1))
plot(a)
plot(extent(b), add = T)
plot(b)
How do I plot a specific row over time? For example I want to plot row 10(layer.1 to 5 is actually year 1 to year 5.
library(raster)
r <- raster(nrow=5, ncol=5)
s <- stack( sapply(1:5, function(i) setValues(r, rnorm(ncell(r), i, 3) )) )
s[]
layer.1 layer.2 layer.3 layer.4 layer.5
[1,] 6.7134890 6.9141251 4.38213123 4.8995302 2.3105321
[2,] 3.4323121 6.1074031 10.12872426 3.6728949 3.2252562
[3,] 4.4370107 3.1397068 5.47572912 1.9692684 4.0064603
[4,] -1.5588723 0.4075960 -0.73333754 6.3589944 5.0355051
[5,] 2.8095750 5.4264553 1.17820009 2.0665198 8.0491221
[6,] 4.3422219 2.1106691 1.08638206 5.0640175 6.8057674
[7,] -3.1072366 -1.1174633 6.28901706 5.0713964 1.8651354
[8,] -0.5628539 2.1868130 1.21288191 0.3114011 3.0452161
[9,] 0.1725606 3.4535112 -1.38043518 3.6439042 5.4005650
[10,] -2.3376856 4.8803363 -0.05927408 7.9275016 4.7013126
[11,] 2.3032655 2.4974161 4.63961513 1.4021305 10.2302589
[12,] 0.4470648 1.1660421 -0.70127807 6.3293479 6.6178080
[13,] 2.5835127 -0.8768809 2.87405383 6.1361518 3.4851934
[14,] -3.2769134 2.1721391 2.17317611 1.4170633 0.6446692
[15,] 1.0771079 -2.5369687 4.89710339 1.8667695 4.4847933
[16,] 7.2532218 3.0210221 0.56993065 2.4564492 6.9473683
[17,] 4.0682441 -0.8198112 4.85259334 7.3296033 8.9541915
[18,] 5.3991328 -0.9818425 1.73782230 2.9220433 4.9865858
[19,] 2.0556183 -0.7470914 5.44869675 1.6452235 4.5236089
[20,] -0.6277883 6.7255821 5.12606765 5.5721351 4.7081256
[21,] 9.0139352 3.1350767 6.59366754 2.0351358 5.1865195
[22,] 7.0598020 0.2869291 7.14368927 9.7213576 0.4251934
[23,] 1.6430309 6.3806803 5.95776881 7.5234383 4.8860264
[24,] 1.9473764 1.5386180 3.89690297 2.5333431 7.7217174
[25,] 0.7960661 -1.5137800 2.84861591 -5.9986647 2.9309536
Thanks in advance.
require(raster)
r <- raster(nrow=5, ncol=5)
set.seed(20) #exact reproducible example
s <- stack( sapply(1:5, function(i) setValues(r, rnorm(ncell(r), i, 3) )) )
s[is.na(s[])] <- 0 #NA values to be replaced (here it is being replaced with zero)
summary(s) # look for minimum and maximum pixel values
#some plot examples
plot(c(s[2]),ylim=c(-8,11)) #range -8 to 11 encompasses minimun and maximum s values
plot(c(s[25]),ylim=c(-8,11))
plot(c(s[600]),ylim=c(-8,11)) #creates an empty plot as there is no such row
plot(s) #plot raster s
If your RasterStack contains spatiotemporal data you could try the
setZ and getZ functions from raster in combination with the
zoo package.
library(raster)
library(zoo)
r <- raster(nrow=5, ncol=5)
## another way to create the RasterStack using init
s <- stack(lapply(1:5, function(i)init(r, fun=rnorm, mean=i, sd=3)))
## Set the time indez of the RasterStack
s <- setZ(s, 2001:2005)
s
> s
class : RasterStack
dimensions : 5, 5, 25, 5 (nrow, ncol, ncell, nlayers)
resolution : 72, 36 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84
names : layer.1, layer.2, layer.3, layer.4, layer.5
min values : -2.0324027, -2.7135752, -2.0341025, -0.8495401, -1.6712431
max values : 1.3919942, 1.9809912, 2.8753805, 1.3746949, 0.6760691
time : 2001, 2002, 2003, 2004, 2005
Let's define a time series with zoo with the content of the cell 10
of s (row 10 of s[]):
z <- zoo(c(s[10]), getZ(s))
> z
2001 2002 2003 2004 2005
0.07586314 0.10235694 -1.28134027 -0.84954013 -1.11903690
There is a method to plot zoo objects:
plot(z)
If you have NA values there are several functions in zoo to manage them (na.approx, na.fill, etc.):
z[4] <- NA
plot(na.approx(z))