1

I have two rasters, with same dimensions (nrow, ncol, and ncell) and same coordinate system. They differ however by their extent, x min/max points:

  • Raster 1: has xmin/max -180, 180, i.e. Americas left, Russia right

  • Raster 2: has 0, 360, i.e. central Africa/Europe left, West Africa/Europe right

I want to align them in R, so that both have -180, 180. I tried several functions such as resample(), projectRaster(), or alignExtent() but all seem to give the right extent, but will basically show only half of the values, i.e. it looks like half of the world disappeared in the new plot.

Which function should I use instead? What is the name of the operation I want to do?

library(raster)

r1 <- raster(nrows=360, ncols=720)
r2 <- raster(nrows=360, ncols=720, xmn=0, xmx=360)

r1[] <- 1:(360*720)
r2[] <- 1:(360*720)

## use projectRaster?
r2_in1 <- projectRaster(r2,r1)

plot(r2_in1)
3

You can do it by cropping the +180 -> +360 chunk out of the raster, setting its extent to -180 -> 0, and then merging it onto the 0 -> +180 chunk of the raster which you crop out with another extent:

These are the three 180-degree wide extents that we need:

> e0 = extent(raster(xmn=-180,xmx=0,ymn=-90,ymx=90))
> e1 = extent(raster(xmn=0,xmx=180,ymn=-90,ymx=90))
> e2 = extent(raster(xmn=180,xmx=360,ymn=-90,ymx=90))

Here's our raster from 0 to 360:

> extent(r2)
class       : Extent 
xmin        : 0 
xmax        : 360 
ymin        : -90 
ymax        : 90 

Crop the part that is from 180 to 360, ie the farthest east (right):

> r2_e = crop(r2,e2)

Set its extent to be -180 to 0, ie on the west (left):

> extent(r2_e)=e0

Now crop out the other half of the raster, and merge it with the relocated half:

> e2_a = merge(r2_e,crop(r2,e1))

Plot and check:

> plot(e2_a)
> dim(e2_a)
[1] 360 720   1

> e2_a
class       : RasterLayer 
dimensions  : 360, 720, 259200  (nrow, ncol, ncell)
resolution  : 0.5, 0.5  (x, y)
extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0 
data source : in memory
names       : layer 
values      : 2.683839e-06, 0.9999899  (min, max)

You should probably make sure there's no single-pixel errors around the join - it seems to have the right dimension but I've not inspected this finely.

0

To complete @Spacedman excellent answer, I found an alternative way:

  1. Extract the coordinates from the source raster,

  2. Compute x2=ifelse(x>180, x-360, x)

  3. Sort the data according to the target raster, and feed the data of source raster according to target order:

    library(purrr)
    library(magrittr)
    library(tidyverse)
    
    r2_xy <- xyFromCell(r2, 1:ncell(r2)) %>% 
          as_data_frame %>%
          mutate(OriginalOrder=1:n(), 
             x2=ifelse(x>180, x-360, x)) %>%
      arrange(desc(y),x2)
    
    r2_new <- raster(nrows=360, ncols=720)
    r2_new[] <- getValues(r2)[r2_xy$OriginalOrder]
    

And here is a test to check @Spacedman solution:

Convert rasters to data-frame:

ras_to_df <- list(r2=r2, e2_a=e2_a) %>%
  map(function(x) getValues(x) %>%
       data.frame(Value=.) %>% as.tbl %>%
       bind_cols(xyFromCell(x, 1:ncell(x)) %>%
                 as.data.frame)  %>%
       arrange(Value)) 

Test 1: once sorted, are all the values the same?

ras_to_df %$% all.equal(r2$Value, e2_a$Value)

Test 2: once changing the x coordinates in the original data to -360 if above 180, and sorting the data, are all the x,y, and values the same?

 ras_to_df %>%
map(~mutate(., x=ifelse(x>180, x-360, x)) %>%
      arrange(x,y)) %$%
all.equal(r2, e2_a)

Both tests returned TRUE :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.