0

I am currently writing code to extract a monthly NDVI for a specific polygon. I got the following code from a YouTube Tutorial and adapted it to my region and sensor. But it gets me the issue:

roi.map is not a function.

What can I do?

Here is the code:

// Extract monthly NDVI

// Define polygon
var roi = ee.Geometry.Polygon(
            [
              [152.52014194065384,-25.67552705424455],
              [152.5238272958403,-25.67552705424455],
              [152.5238272958403,-25.674115299750213],
              [152.52014194065384,-25.674115299750213],
              [152.52014194065384,-25.67552705424455]
            ]
          );

// NDVI function
var addNDVI = function(image){
  var nir = image.select('B8');
  var red = image.select('B4');
  var ndvi = nir.subtract(red).divide(nir.add(red)).rename('NDVI')
  return image.addBands(ndvi)
}

// Monthly NDVI summary for polygon
var sentinel2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED")
                .map(addNDVI)
                .select('NDVI')
                .filterDate('2015-01-01','2016-12-31')
                .map(function(image){
                  var d = ee.Date(ee.Number(image.get('system:time_start')));
                  var m = ee.Number(d.get('month'));
                  var y = ee.Number(d.get('year'));
                  return image.set({'month':m,'year':y});
                })
                
var months = ee.List.sequence(1,12)
var years = ee.List([2015,2016,2017,2018,2019,2020,2021,2022])

var byYearMonth = ee.ImageCollection.fromImages(
      years.map(function(y) {
        return months.map(function(m) {
          return sentinel2.filterMetadata('year', 'equals', y)
                          .filterMetadata('month', 'equals', m)
                          .select('NDVI').median()
                          .set('year', y)
                          .set('month', m)
                          .set('date', ee.Date.fromYMD(y,m,1));
        });
      }).flatten()
    );

var proj = ee.Image(sentinel2.first()).projection()
   
var NDVI_roi = byYearMonth.map(function(image) {
  var features = roi.map(function(f) {
    return f.set('date', image.get('date'), 
                'month', image.get('month'),
                'year', image.get('year'));
  });
  return image.reduceRegions(features, ee.Reducer.median(), 250, proj); 
}).flatten();

print(NDVI_roi.limit(10));

1 Answer 1

1

The roi needs to be a FeatureCollection but it was only a geometry in your current code. You can change it before using the map() function. To add NDVI, you don't need to create another function, you can easily do it with the normalizedDifference() function. The code has some issues that you will face after this correction.

  1. You can set a filterBounds your roi for the overall imageCollection. Otherwise you can get a memory limit error.
  2. Sentinel-2 images are available from 23 June 2015. You will not get previous images, if you mention previous dates in filterDate(). It will throw an error.
  3. The list of years should match the years mentioned in the filterDate()

I have modified the code addressing these points.

var roi = ee.Geometry.Polygon(
            [
              [152.52014194065384,-25.67552705424455],
              [152.5238272958403,-25.67552705424455],
              [152.5238272958403,-25.674115299750213],
              [152.52014194065384,-25.674115299750213],
              [152.52014194065384,-25.67552705424455]
            ]
          );


// Filter the Sentinel2 collection
var sentinel2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED")
                .filterDate('2016-01-01','2022-12-31')
                .filterBounds(roi)
                

// NDVI of all months
var NDVI = sentinel2.map(function(image){
                  var d = ee.Date(ee.Number(image.get('system:time_start')));
                  var m = ee.Number(d.get('month'));
                  var y = ee.Number(d.get('year'));
                  var ndvi=image.normalizedDifference(['B8','B4']).rename('NDVI')
                  return ndvi.set({'month':m,'year':y});
})      

var months = ee.List.sequence(1,12)
var years = ee.List.sequence(2016,2022)

var byYearMonth = ee.ImageCollection.fromImages(
      years.map(function(y) {
        return months.map(function(m) {
          return NDVI.filterMetadata('year', 'equals', y)
                          .filterMetadata('month', 'equals', m).select('NDVI').median()
                          .set('year', y)
                          .set('month', m)
                          .set('date', ee.Date.fromYMD(y,m,1));
        });
      }).flatten()
    );

var proj = ee.Image(NDVI.first()).projection()
   
var NDVI_roi = byYearMonth.map(function(image) {
  var features = ee.FeatureCollection(roi).map(function(f) {
    return f.set('date', image.get('date'), 
                'month', image.get('month'),
                'year', image.get('year'));
  });
  return image.reduceRegions(features, ee.Reducer.median(), 250, proj); 
}).flatten();

print(NDVI_roi.limit(10));

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.