0

I am creating several bands of spectral indexes by reducing the S2 TOA image collection. For each spectral index, I am extracting the pixel values at specific locations (a point shapefile represent the locations) and exporting the result to a .csv tables. Is it possible to export the results in a single table? Please see the script I am using below. I apology but I cannot share the feature collection, however it is a simple shapefile of points.

// First define an area of interest
var lat = 65.64; 
var lng = 34.35;
var point = ee.Geometry.Point(lat, lng); 
//var aoi = point.buffer(100000); // Create an area (1km buffer around point)
var country = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')
.filter(ee.Filter.eq('country_co', 'AF'));
var aoi = country;

Map.setCenter(lat, lng, 5); // Center the map on this location, zoom level 10

var start = '2019-03-29'; // initial date of the image collection
var end = '2019-05-05'; //final date of the image collection

/**
 * Function to mask clouds using the Sentinel-2 QA band
 * @param {ee.Image} image Sentinel-2 image
 * @return {ee.Image} cloud masked Sentinel-2 image
 */
function maskS2clouds(image) {
  var qa = image.select('QA60');

  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000);
}


// reduce NDVI over an image collection
// Function to calculate and add an NDVI band
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');
  return image.addBands(ndvi);
};

// reduce NDWI (1-2) over an image collection
// Functions to calculate and add an NDWI (1-2) bands

var addNDWI1 = function(image) {
  var ndwi1 = image.normalizedDifference(['B8A', 'B11']).rename('NDWI1');
  return image.addBands(ndwi1);
};

var addNDWI2 = function(image) {
  var ndwi2 = image.normalizedDifference(['B8A', 'B12']).rename('NDWI2');
  return image.addBands(ndwi2);
};

//reduce Red-Edge NDVI (1-3) over the image collection 
// Functions to calculate and add an RE-NDVI (1-3) bands

var addRENDVI1 = function(image) {
  var rendvi1 = image.normalizedDifference(['B8A','B5']).rename('RENDVI1');
  return image.addBands(rendvi1);
};

var addRENDVI2 = function(image) {
  var rendvi2 = image.normalizedDifference(['B8A','B6']).rename('RENDVI2');
  return image.addBands(rendvi2);
};

var addRENDVI3 = function(image) {
  var rendvi3 = image.normalizedDifference(['B8A','B7']).rename('RENDVI3');
  return image.addBands(rendvi3);
};

// Download the Sentinel-2 imagery collection
var imgs = ee.ImageCollection('COPERNICUS/S2')
    .filterDate(start, end)
    .filterBounds(aoi)
    .map(maskS2clouds)
    .map(addNDVI)
    .map(addNDWI1)
    .map(addNDWI2)
    .map(addRENDVI1)
    .map(addRENDVI2)
    .map(addRENDVI3);
    
// Extract NDVI band and create NDVI max composite image
var NDVI = imgs.select(['NDVI']);
//var NDVImed = NDVI.median(); 
var NDVImax = NDVI.max();
//var NDVImin = NDVI.min();

// Extract NDWI bands and create NDVI max composite images
var NDWI1 = imgs.select(['NDWI1']);
var NDWI1max = NDWI1.max();

var NDWI2 = imgs.select(['NDWI2']);
var NDWI2max = NDWI2.max();


// Extract Red-edge NDVI bands and create R-E NDVI max composite images

var RENDVI1 = imgs.select(['RENDVI1']);
var RENDVI1max = RENDVI1.max();

var RENDVI2 = imgs.select(['RENDVI2']);
var RENDVI2max = RENDVI2.max();

var RENDVI3 = imgs.select(['RENDVI3']);
var RENDVI3max = RENDVI3.max();

//Extract Spectral Indexes of Yield Locations (at pixel level) and export results

var YieldLocations = ee.FeatureCollection(table);

var YLndviM = NDVImax.reduceRegions(YieldLocations, ee.Reducer.max(), 1);
var YLndwi1M = NDWI1max.reduceRegions(YieldLocation, ee.Reducer.max(), 1);
var YLndwi2M = NDWI2max.reduceRegions(YieldLocation, ee.Reducer.max(), 1);
var YLrendvi1M = RENDVI1max.reduceRegions(YieldLocation, ee.Reducer.max(), 1);
var YLrendvi2M = RENDVI2max.reduceRegions(YieldLocation, ee.Reducer.max(), 1);
var YLrendvi3M = RENDVI3max.reduceRegions(YieldLocation, ee.Reducer.max(), 1);

Export.table.toDrive(YLndviM,
"Max_VI",
"2019",
"MaxNDVI_2019");

Export.table.toDrive(YLndwi1M,
"Max_WI1",
"2019",
"MaxNDWI1_2019");

Export.table.toDrive(YLndwi2M,
"Max_WI2",
"2019",
"MaxNDWI2_2019");

Export.table.toDrive(YLrendvi1M,
"Max_RE1",
"2019",
"MaxRENDVI1_2019");

Export.table.toDrive(YLrendvi1M,
"Max_RE2",
"2019",
"MaxRENDVI2_2019");

Export.table.toDrive(YLrendvi1M,
"Max_RE3",
"2019",
"MaxRENDVI3_2019");

 
2

I'm assuming that you want one output row per input point, with columns for each of the properties you're computing. In that case, the best thing to do is to combine your multiple reduceRegions calls into a single one — that way you get one collection as a result, and it will be much more efficient because it's processing the input table and image collection fewer times.

Starting with your imgs, we can produce the max composites all at once:

var composites = imgs
  .select(['NDVI', 'NDWI1', 'NDWI2', 'RENDVI1', 'RENDVI2', 'RENDVI3'])
  .max();

If you want to use something other than maximum for one of the composites, it's possible but a little more verbose:

var composites = imgs
  .select(['NDVI', 'NDWI1', 'NDWI2', 'RENDVI1', 'RENDVI2', 'RENDVI3'])
  .reduce(
    // Set up one specific reducer, with specific name, per band
    ee.Reducer.median().setOutputs(['NDVImed'])  
      .combine(ee.Reducer.max().setOutputs(['NDWI1max']))
      .combine(ee.Reducer.max().setOutputs(['NDWI2max']))
      .combine(ee.Reducer.max().setOutputs(['RENDVI1max']))
      .combine(ee.Reducer.max().setOutputs(['RENDVI2max']))
      .combine(ee.Reducer.max().setOutputs(['RENDVI3max'])));

(This is the same kind of operation as before; imgs.max() is a shorthand for imgs.reduce(ee.Reducer.max()). We just have to write out the complex reducer when we want it to do different things to different bands.)

Once you have all your composites in one image like this, you can then reduceRegions to get all the results in one table:

var table = composites.reduceRegions(YieldLocations, ee.Reducer.max(), 1);

Export.table.toDrive(table, ...);
2
  • The first proposal works fine while the "verbose" alternative returned the following: "Error: Reducer.combine: Duplicate output name: 'max'." – Lollo Jun 22 '20 at 11:32
  • @Lollo Should be fixed now. – Kevin Reid Jun 22 '20 at 14:02

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.