TransWikia.com

Changing extent of raster in loop using R

Geographic Information Systems Asked by Ferdi Karp on June 4, 2021

I have raster objects of a certain extent (0, 360, -90, 90) and I want to change that extent for all of them to a different extent (-180, 180, -90, 90).
The thing is that I have my objects (raster layers) in a list and I want to change the extent with one step in a loop.

My approach (example)

st_ext <- extent(-180, 180, -90, 90)

  for (i in 1:NROW(r)){
    r[[i]] <- setExtent(r[[i]], st_ext)
  }

When I do it like this, the extent does not change but when I use the exact same command where I put in "i" manually, the extent changes like it should.

r[[1]] <- setExtent(r[[1]], st_ext)

Why does this happen and how I can make it work with the loop?

I also tried

extent(r[[i]]) <- st_ext

and

xmin(r[[i]]) <- -180
xmax(r[[i]]) <- 180

But when using all of those those in a loop, the extent remains unchanged.

3 Answers

Although not directly answering your question, I think it is important to point out that if you want to change the extent of raster x from (0, 360, -90, 90) to (-180, 180, -90, 90) you should use rotate(x), not setExtent.

The loop should work as Spacedman shows. Can you make an example where it does not? It seems clear that your problem originates earlier on --- you say you used mget which is always the wrong approach.

You also say that the object names contain a -. Do you mean the layer names? R object names cannot contain the minus sign, for obvious reasons. (well unless you backtick them as in `a-b`, but how much self-inflicted pain are you willing to suffer?)

Can't you use a RasterStack?

Correct answer by Robert Hijmans on June 4, 2021

Are you sure your r is a list? This works for me:

I'm going to set the extents the other way round from you, but that doesn't matter:

> st_ext <- extent(0, 360, -90, 90)

which I'm doing because the simplest way of making a raster sets the extent to -180:180:

> v = raster()
> extent(v)
class      : Extent 
xmin       : -180 
xmax       : 180 
ymin       : -90 
ymax       : 90 

Now make a list of them:

> r = list(v,v,v,v)

Check the first one:

> extent(r[[1]])
class      : Extent 
xmin       : -180 
xmax       : 180 
ymin       : -90 
ymax       : 90 

Now loop and set new extent:

> for(i in 1:4){
   r[[i]] = setExtent(r[[i]], st_ext)
 }

And they've changed:

> extent(r[[1]])
class      : Extent 
xmin       : 0 
xmax       : 360 
ymin       : -90 
ymax       : 90 

Are you sure your r is a list of rasters?

Answered by Spacedman on June 4, 2021

Thank you all for your contributions! No matter what combination of commands I tried it didn't appear to work with a loop. However, the answers above helped me to find a workaround.

A little more background information: I am working with multiple datasets and the mget function helped me organize the objects I use in a list. These lists can also be made into RasterStacks with little effort. In the code I worked out below, I make a list out of the lists I created. Each list is then made into a RasterStack as I rotate that whole RasterStack.

listP_m <- mget(ls(pattern="^P_.*mean$"))
   
listF1rcp26m <- mget(ls(pattern="^F1rcp26.*mean$"))
listF2rcp26m <- mget(ls(pattern="^F2rcp26.*mean$"))

listF1rcp60m <- mget(ls(pattern="^F1rcp60.*mean$"))
listF2rcp60m <- mget(ls(pattern="^F2rcp60.*mean$"))

listALL_m <- mget(ls(pattern="^list.*m$"))

  for (i in 1:NROW(listALL_m)){
      for (j in 1:NROW(listALL_m[[i]])){
        if(length(listALL_m[[i]])>0){
        assign(names(listALL_m[i]), rotate(stack(listALL_m[[i]])))
        }
    }}

There are easier ways, I know, but this approach gave the desired solution with the least amount of effort required in changing my code.

Answered by Ferdi Karp on June 4, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP