Search code examples
rlistloopsrenameraster

Ordering files numerically based on the middle of the character string in r


I have a list of .tif imagery in a directory, which I loop through to do some raster math later on. I would like the .tif files to be ordered by date, so that when the loop is run I know which date corresponds to which .tif file based on its order in the list. I think I need to either rename the files, or figure out some way to sort them after the loop.

For example:

rastlist <- list.files(here::here("data", "s2_cropped"), 
                       pattern = '.tif$', all.files = TRUE, full.names = TRUE)
rastlist
[1] "/data/s2_cropped/S2A2A_20200307_135_36MYD_BOA_10.tif"
[2] "/data/s2_cropped/S2A2A_20200605_135_36MYD_BOA_10.tif" 
[3] "/data/s2_cropped/S2A2A_20200705_135_36MYD_BOA_10.tif" 
[4] "/data/s2_cropped/S2A2A_20200804_135_36MYD_BOA_10.tif" 
[5] "/data/s2_cropped/S2A2A_20200903_135_36MYD_BOA_10.tif" 
[6] "/data/s2_cropped/S2A2A_20201003_135_36MYD_BOA_10.tif" 
[7] "/data/s2_cropped/S2A2A_20201102_135_36MYD_BOA_10.tif" 
[8] "/data/s2_cropped/S2A2A_20201202_135_36MYD_BOA_10.tif" 
[9] "/data/s2_cropped/S2B2A_20200102_135_36MYD_BOA_10.tif" 
[10] "/data/s2_cropped/S2B2A_20200211_135_36MYD_BOA_10.tif" 
[11] "/data/s2_cropped/S2B2A_20200401_135_36MYD_BOA_10.tif" 
[12] "/data/s2_cropped/S2B2A_20200501_135_36MYD_BOA_10.tif" 

I think it's ordering alphabetically based on the first part of the string "S2A2A" & "S2B2A", but I want it ordered by the date like this:

rastlist
[1] "/data/s2_cropped/S2B2A_20200102_135_36MYD_BOA_10.tif" 
[2] "/data/s2_cropped/S2B2A_20200211_135_36MYD_BOA_10.tif"
[3] "/data/s2_cropped/S2A2A_20200307_135_36MYD_BOA_10.tif"
[4] "/data/s2_cropped/S2B2A_20200401_135_36MYD_BOA_10.tif" 
[5] "/data/s2_cropped/S2B2A_20200501_135_36MYD_BOA_10.tif"
[6] "/data/s2_cropped/S2A2A_20200605_135_36MYD_BOA_10.tif" 
[7] "/data/s2_cropped/S2A2A_20200705_135_36MYD_BOA_10.tif" 
[8] "/data/s2_cropped/S2A2A_20200804_135_36MYD_BOA_10.tif" 
[9] "/data/s2_cropped/S2A2A_20200903_135_36MYD_BOA_10.tif" 
[10] "/data/s2_cropped/S2A2A_20201003_135_36MYD_BOA_10.tif" 
[11] "/data/s2_cropped/S2A2A_20201102_135_36MYD_BOA_10.tif" 
[12] "/data/s2_cropped/S2A2A_20201202_135_36MYD_BOA_10.tif" 

I'm then looping through to do some raster math on each stack. I don't know if this part of the code matters too much but it looks something like this.

ndvi_list <- list() #empty vector to store ndvi values

for  (i in 1:length(rastlist)) {

b <- brick(rastlist[[i]]
ndvi_list[i] <- (b[[4]] - b[[1]]) / (b[[4]] + b[[1]])

}

The result of the loop is 12 rasters in a list

Solution

  • We could extract the date substring, convert to Date class, order and use that index for ordering

    rastlist2 <- rastlist[order(as.Date(sub(".*_(\\d{8})_.*", 
             "\\1", rastlist), '%Y%m%d'))]
    

    -output

    rastlist2
    #[1] "/data/s2_cropped/S2B2A_20200102_135_36MYD_BOA_10.tif" "/data/s2_cropped/S2B2A_20200211_135_36MYD_BOA_10.tif"
    #[3] "/data/s2_cropped/S2A2A_20200307_135_36MYD_BOA_10.tif" "/data/s2_cropped/S2B2A_20200401_135_36MYD_BOA_10.tif"
    #[5] "/data/s2_cropped/S2B2A_20200501_135_36MYD_BOA_10.tif" "/data/s2_cropped/S2A2A_20200605_135_36MYD_BOA_10.tif"
    #[7] "/data/s2_cropped/S2A2A_20200705_135_36MYD_BOA_10.tif" "/data/s2_cropped/S2A2A_20200804_135_36MYD_BOA_10.tif"
    #[9] "/data/s2_cropped/S2A2A_20200903_135_36MYD_BOA_10.tif" "/data/s2_cropped/S2A2A_20201003_135_36MYD_BOA_10.tif"
    #[11] "/data/s2_cropped/S2A2A_20201102_135_36MYD_BOA_10.tif" "/data/s2_cropped/S2A2A_20201202_135_36MYD_BOA_10.tif"
    

    data

    rastlist <- c("/data/s2_cropped/S2A2A_20200307_135_36MYD_BOA_10.tif", "/data/s2_cropped/S2A2A_20200605_135_36MYD_BOA_10.tif", 
    "/data/s2_cropped/S2A2A_20200705_135_36MYD_BOA_10.tif", "/data/s2_cropped/S2A2A_20200804_135_36MYD_BOA_10.tif", 
    "/data/s2_cropped/S2A2A_20200903_135_36MYD_BOA_10.tif", "/data/s2_cropped/S2A2A_20201003_135_36MYD_BOA_10.tif", 
    "/data/s2_cropped/S2A2A_20201102_135_36MYD_BOA_10.tif", "/data/s2_cropped/S2A2A_20201202_135_36MYD_BOA_10.tif", 
    "/data/s2_cropped/S2B2A_20200102_135_36MYD_BOA_10.tif", "/data/s2_cropped/S2B2A_20200211_135_36MYD_BOA_10.tif", 
    "/data/s2_cropped/S2B2A_20200401_135_36MYD_BOA_10.tif", "/data/s2_cropped/S2B2A_20200501_135_36MYD_BOA_10.tif"
    )