[GIS] Calculating NDVI per region, month & year with Google Earth Engine

google-earth-enginegoogle-earth-engine-javascript-apilandsatndvi

This question refers to post: https://stackoverflow.com/questions/53280885 on stackoverflow. It was recommended by a user to repost here.

I have modified the code posted by @Kel Markert https://code.earthengine.google.com/349615d7802d59f677181bef0badad9f to attempt to get a maximum monthly NDVI value from a small polygon over a number of years from Landsat 8 in Google Earth Engine and export to CSV.

But I keep getting an error of

Dictionary.get, argument 'key': Invalid type. Expected: String.
Actual: List

Any advice on how to fix this?

Code Link
Google Earth Script

Table Link

    var region = table,
L8 = ee.ImageCollection("LANDSAT/LC08/C01/T1_TOA");

var cloudlessNDVI = L8.map(function(image) {
  // Get a cloud score in [0, 100].
  var cloud = ee.Algorithms.Landsat.simpleCloudScore(image).select('cloud');

  // Create a mask of cloudy pixels from an arbitrary threshold.
  var mask = cloud.lte(20);

  // Compute NDVI.
  var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');

  // Return the masked image with an NDVI band.
  return image.addBands(ndvi).updateMask(mask);
});

var startDate = ee.Date('2013-05-01'); // set analysis start time
var endDate = ee.Date('2019-12-31'); // set analysis end time

// calculate the number of months to process
var nMonths = ee.Number(endDate.difference(startDate,'month')).round();

// get a list of time strings to pass into a dictionary later on
var monList = ee.List.sequence(0, nMonths).map(function (n) {
  return startDate.advance(n, 'month').format('YYYMMdd');
})
print(monList)

var result = region.map(function(feature){
  // map over each month
  var timeSeries = ee.List.sequence(0,nMonths).map(function (n){
    // calculate the offset from startDate
    var ini = startDate.advance(n,'month');
    // advance just one month
    var end = ini.advance(1,'month');
    // filter and reduce
    var data = cloudlessNDVI.filterDate(ini,end).max().reduceRegion({
      reducer: ee.Reducer.max(),
      geometry: feature.geometry(),
      scale: 30
    });
    // get the value and check that it has data
    var val = ee.Number(data.get(['ndvi']));
    val = ee.Number(ee.Algorithms.If(val,val,-999));
    // return max
    return val;
  });
  // create new dictionary with date strings and values
  var timeDict = ee.Dictionary.fromLists(monList,timeSeries);
  // return feature with a timeseries property and results
  return feature.set(timeDict);
});

// print to see if it is doing what we expect...
print(result);

// Export the data to a table for further analysis
Export.table.toDrive({
  collection:result,
  description:"MCM1_NDVI",
  fileFormat:"CSV",
  //selectors:["HRpcode","timeseries"]
})

Best Answer

The line: var val = ee.Number(data.get(['ndvi']))

needs to be changed to var val = ee.Number(data.get('NDVI'))

since you have renamed 'ndvi' to 'NDVI' in your code.

Related Question