1

I'm running a randomforest on a raster stack/brick in R. I know how to rename individual layers in the stack, but since my stacks have numerous Landsat scenes, I was hoping to loop through the stack. I'm doing this because I want the variable importance plot (varImgPlot) from the randomforest package to display shorter names than the entire raw Landsat code. My code is as follows:

for (i in 1:name_len){
  name_var<-names(stack_analyze)[i]
  if (nchar(name_var)>18){
    name_date<-str_sub(name_var, 18, 26)
    name_band<-str_sub(name_var, -2, -1)
    new_name<-paste(name_date, name_band, sep = '')
    names(stack_analyze)[1]<-new_name
  }
  else{
    print('name small, no change made')
  }
}

Some of the layers are derived, so I have an effective, shorter name for them already. I'm trying to select larger layers here and then change them accordingly based on a simple positional str_sub(). When I run this code, it doesn't even work for the first name. It renames to the wrong band name for the first layer, and then doesn't do anything for the rest. I get the correct number of print statements for the shorter names, so at least I know the loop is going through the if statements. Any help to make this work so I don't have to go name dozens of bands manually?

2 Answers 2

1

I messed up. I'm indexing in R incorrectly in a loop. I fixed this with:

counter<-1
names(stack_analyze)
for (i in 1:name_len){
  print(counter)
  current_name<-names(stack_analyze)[counter]
  if (nchar(current_name)>18){
    new_band<-str_sub(current_name, -2,-1)
    new_date<-str_sub(current_name, 18,  25)
    new_name<-paste(new_band, new_date,sep = '_')
    print(new_band)
    print(new_date)
    print(new_name)
    names(stack_analyze)[counter]<-new_name
  }
  counter<-counter+1
}
names(stack_analyze)  

I'm not 100% sure why this change worked, but it did.

1

You are over complicating things quite a bit. The names element is a vector and can be treated as such. I am using terra because raster will be depreciated and one should be moving workflows to the new package. However, it should work exactly the same for a raster stack/brick object.

Create a raster with 10 layers and assign random names that are 20 characters long.

library(terra)

r <- rast(ext(1008135.6017, 1753140.3853, -577835.4577, -225208.3466),
          nlyrs=10, resolution=5000)
  names(r) <- do.call(paste0, replicate(20, sample(LETTERS, 
                      length(names(r)), TRUE), FALSE))
    names(r)

Now, we want to shorten the names to no more than 10 characters. As you can see, we are operating directly on the names vector associated with the object. This is really no different than if we were altering column names in a data.frame.

names(r) <- substr(names(r), 1, 10)
  names(r)

We can expand this and take the first 4 and last 4 characters, showing how you can subset portions of a fixed string and recombine them using a seperator (need to rerun original random names to have enough characters).

names(r) <- paste(substr(names(r), 1, 4), 
       substr(names(r), 17, 20),sep="_")
  names(r)

If you wanted to do something tricky like split the string and recombine it you could do this via lapply on names and just unlist the results that are piped into the names vector of the raster object.

Here we create an example vector with underscores separating 3 groups of strings (often landsat names have underscores separating the different granule elements).

( n <- unlist(lapply(1:10, function(i)
         paste(do.call(paste0,replicate(4, sample(LETTERS, 3, 
         TRUE), FALSE)), collapse = "_") )) )

Now the we have the above example, we split on the underscore, drop the middle name element and recombine. This could be done directly to the names vector and the results piped right back in.

unlist(lapply(strsplit(n, "_"), function(i) { 
       paste(i[1],i[2],sep="_")}))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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