Sorting raster stack by dates in R

I need suggestion on how to sort a raster stack by dates. A reproducible example is in the following:

``````library(raster)
``````

Create a reproducible rasterstack;

``````set.seed(123)
r1 <- raster(nrows = 6, ncols = 5, res = 30, xmn = 267195, xmx = 267375, ymn = 4016985, ymx = 4017135)
rr <- lapply(1:24, function(i) setValues(r1, runif(ncell(r1), min = -10000, max = 10000)))
ndvi <- stack(rr)
crs(ndvi) <- "+proj=utm +zone=43 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0"
``````

Create date function;

``````dt <-as.data.frame(as.Date(c(
'2017-01-03','2017-02-04','2018-11-22','2019-05-17','2013-04-14','2013-04-30',
'2013-05-16','2013-06-01','2013-06-17','2013-07-03','2013-07-19','2013-08-04',
'2013-08-20','2013-09-05','2013-10-07','2013-10-23','2013-11-08','2013-11-24',
'2013-12-10','2013-12-26','2014-01-11','2014-01-27','2014-02-12','2014-02-28')))
``````

Attach date to rasterstack;

``````ndvi <- setZ(ndvi, dt[,1], "SampleDate")
dates <- getZ(ndvi)
class(getZ(ndvi))
print(ndvi)
``````

Now how can I sort or order the raster stack by dates (the oldest layer as the first layer and so on)?

• A smaller example would be easier to see and work with! What works for ten dates will work for 768. Oct 5 '20 at 17:15
• What if you change the names of your rasters to the dates or ranked number according to the dates and order the names. See the answer given: stackoverflow.com/questions/27483664/… Oct 5 '20 at 17:38

Use double brackets to re-order layers of a stack, and `order` to get the ordering. I stripped your example down to the first 10:

``````> ndvi_order = ndvi[[order(dates)]]
> ndvi_order
class      : RasterStack
dimensions : 5, 6, 30, 10  (nrow, ncol, ncell, nlayers)
resolution : 30, 30  (x, y)
extent     : 267195, 267375, 4016985, 4017135  (xmin, xmax, ymin, ymax)
crs        : +proj=utm +zone=43 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
names      :   layer.5,   layer.6,   layer.7,   layer.8,   layer.9,  layer.10,   layer.1,   layer.2,   layer.3,   layer.4
min values : -9790.658, -7778.071, -6953.068, -9046.727, -9599.514, -9873.984, -9158.809, -9507.726, -9987.505, -8785.589
max values :  9684.384,  7493.647,  9712.818,  9222.096,  9387.128,  9642.807,  9885.396,  9260.485,  9699.140,  9089.477
SampleDate  : 2013-04-14, 2013-04-30, 2013-05-16, 2013-06-01, 2013-06-17, 2013-07-03, 2017-01-03, 2017-02-04, 2018-11-22, 2019-05-17
``````
• Nice solution. Perfect. Thanks Oct 6 '20 at 12:36

So, I never use the Z slot in stack objects. It is just as easy to manage a date vector. Let's assume that you did some sort of string manipulation to get the dates from the raster objects in your stack. Now, you want to sort the stack so that the date sequence is ordered correctly.

You already have a date vector but, please note that you do not need to coerce to a data.frame and it is good practice to explicitly define the date-time format when creating a date object.

First, I am grabbing a subsample of your dates so results are easier to see.

``````( dt.sub <- dt[sample(1:length(dt), 20)] )
``````

Now, we can sort the dates and return an index of the original position, which relates to the raster stack.

``````( didx <- sort.int(dt.sub, index.return=TRUE) )
``````

You can use the returned index `x\$ix` to resort the stack using a simple double bracket.

``````dates <- sort.int(dt, index.return=TRUE)\$x
ndvi <- ndvi[[sort.int(dt, index.return=TRUE)\$ix]]
``````

You now have a sorted dates vector and the raster stack is reordered accordingly. When I perform timeseries analysis I use the dates vector to query the raster stack using an index. This is where the `which` function if useful.

``````which(dates > "2015-12-31")

date.sub <- dates[which(dates > "2015-12-31")]
ndvi.sub <- ndvi[[which(dates > "2015-12-31")]]
``````
• Thanks for the solution. I also learned from your solution how to use which() function. Oct 6 '20 at 12:36