Google Earth Engine – Add Date to Band Names in ImageCollection

google-earth-enginemulti-band

I'm new to the GEE platform and I'm struggling with something very basic. I want to extract pixel values by points from an ImageCollection and I want my ouput to be a table in a wide format. To do this and apply my reducer, I exploded the ImageCollection and, instead of having a number X of images with Y bands for each image, treated all rasters as bands of only one image.

Here is the code:

var band_Names = ee.List(['Blue', 'Green', 'Red', 'NIR', 'SWIR 1', 'SWIR 2', 'pixel_qa']);

var LC08_collection = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
  .filterDate('2013-01-01','2019-12-31')
  .filterBounds(points)
  .map(function(image){
  return image.rename(['Aerosol', 'Blue', 'Green', 'Red', 'NIR', 'SWIR 1', 'SWIR 2', 'TIRS 1', 'TIRS 2', 'sr_aerosol', 'pixel_qa', 'radsat_qa']);
  })
  .select(band_Names);

var mergeBands = function(image, previous) {
  return ee.Image(previous).addBands(image);
};

var collection_asImage = LC08_collection.iterate(mergeBands, ee.Image([]));
var collection_asImage = ee.Image(collection_asImage).float();

var extraction = collection_asImage.reduceRegions({
  collection: points,
  reducer: ee.Reducer.first(),
  scale: 30,
});

Export.table.toDrive({
  collection: ee.FeatureCollection(extraction), 
  description: 'Pixel values', 
  fileFormat: 'CSV', 
});

All is well and good, but, in this way, the field names of my dataset will look like this:

'Id' | 'Class' | 'Blue' | 'Green' | 'Red' | 'NIR' | 'SWIR 1' | 'SWIR 2' | 'pixel_qa' | 'Blue_1' | 'Green_2'...
1
2
3
4
5
6

Which is great, except for the fact that after the first set of bands there is the number that underlines the iteration of an element ('Blue_1'), which I don't want. Instead, I want to have the date of the image from which the value of that band comes from ('Blue_2013-05-20' for example). I got the date as a list in this way:

var dates = LC08_collection
  .map(function(image) {
    return ee.Feature(null, {'date': image.date().format('YYYY-MM-dd')});
  })
  .aggregate_array('date');
print(dates, 'Date list');

But I don't know how to rename the bands. I thought of renaming them before exploding the collection and merging all the bands, writing a function that will be mapped over the ImageCollection which returns the band names already there and adds the element of dates array, but I don't know how to achieve this result. Does anybody know how to help me?

Thanks in advance.

Best Answer

I am not sure if I understand your question, but I guess you struggle making one image of a collection, and rename the band to its according system:time_start property, formatted human readable.

Your question then is very similar to this question. For your example, most easiest would be:

var collection_asImage = LC08_collection.toBands();

This adds the sensor ID, the zones and the date in front of the band name. Possibly, this suites your needs.

The problem with your suggestion, only adding the date at the end, is that there could be multiple Landsat image with a similar date. Thus, the image band names will have similar names and the script will fail. A solution could be manually adding the zone:

// rename the bands using the system:time_start property (and zone if necesarry)
var LC08_collection_renamedBands = LC08_collection.map(function(image) {
    var dateFormatted = ee.String('_').cat(image.date().format('YYYY-MM-dd'));
    var zones = image.getString('system:index').slice(4,11);
    return image.rename(image.bandNames().map(function(bandName){
      return ee.String(bandName).cat(dateFormatted)
        .cat(zones);
    }));
  });

// Apply the function toBands() on the image collection to set all bands into one image
var collection_asImage = LC08_collection_renamedBands.toBands();

// then remove the by default prefixed ID 
var names = collection_asImage.bandNames();
// rename the bandnames 
var newNames = names.map(function(name){
  var ind = names.indexOf(name);
  return ee.String(names.get(ind)).slice(21);
});
var multiband = collection_asImage.rename(newNames);

Link to script option 1, and link option 2

Related Question