2

I want to calculate the mean NDVI per region (admin level 3, also called woreda), month and year. So my end result would look something like this:

regions    year    month   NDVI   
---------------------------------
region_1     2010       1     0.5  
region_1     2010       2    -0.6  
region_1     2010       3     0.7  
region_1     2010       4    -0.3  
region_1     2010       5     0.4  
region_1     2010       6    -0.5  
region_1     2010       7     0.5  
region_1     2010       8    -0.7  
region_1     2010       9     0.8  
region_1     2010       10   -0.55  
region_1     2010       11   -0.3  
region_1     2010       12   -0.2  
region_2     2010       1     0.5  
region_2     2010       2    -0.6  
region_2     2010       3     0.7  
region_2     2010       4    -0.3  
region_2     2010       5     0.4  
region_2     2010       6    -0.5  
region_2     2010       7     0.5  
region_2     2010       8    -0.7  
region_2     2010       9     0.8  
region_2     2010       10   -0.55  
region_2     2010       11   -0.3  
region_2     2010       12   -0.2  
...          ...       ...    ...

My code basically does this for a predetermined region in the var modisNDVI. However I want my code to be able to do this for 2010 untill 2015, for each month for each region.

How can I do this without writing more for loops (the iterating through the years and months)?

Should I be using reduceRegion or .map() in order to skip (all) the for loops?

I've made an attempt to use reduceRegions but failed to apply this to an imageCollection.

// import data
var region = ee.FeatureCollection("ft:1zRUOJL1LYCPJj-mjP6ZRx8sxYKNH8EwDw3EPP66K"),
modisNDVI = ee.ImageCollection("MODIS/MCD43A4_006_NDVI");

// Get NDVI 
var modisNDVI = ee.ImageCollection(modisNDVI.filterDate('2015-01-01', '2015-06-01'));
var woredaNames = region.aggregate_array("HRpcode")

// do something so I can get monthly data for each year (2010-2015) for earch woreda (690)
// I don't want to write another for loop for the year and month what is a more optimized way?

// Processing all the 690 takes long, for this example I've used 10 woreda's
for (var woreda=0; woreda < 10 ;woreda++){

    // Focus on one region:
    var focusRegion = region.filter(ee.Filter.eq('system:index', String(woreda)));

    // Clip modis image on focused region:
    var focus_NDVI_clip = modisNDVI.mean().clip(focusRegion);

    // aggregate mean over geometry from focused region:
    var mean_dict = focus_NDVI_clip.reduceRegion({
    reducer: ee.Reducer.mean(),
    geometry: focusRegion.geometry(),
    scale: 500,
    });

    // Append index to mean_dictionary and print it (eventually this should turn into a list):
    var woreda_code = ee.List(woredaNames).get(woreda);
    mean_dict = mean_dict.set('Woreda_code', ee.String(woreda_code));
    print(mean_dict);}

edit: I tried to use the script that Bert Coerver proposed. However this calculates the mean NDVI for each date (I only need it for one month per region). Subsequently the daily calculation of the ndvi per region results in a run time error.

2

Basically, in GEE, you always want to avoid using for-loops. Better use "map" or "iterate" instead.

Here is a script that more or less does what you want to do (the format of the output is a bit different than what you ask) and I think you might run into a time-out error if you expend the dates of your "filterDate". In that case you could try to export your data as a csv-file (https://code.earthengine.google.com/491e806958676d27fd4e504f7b8de266).

// import data.
var regions = ee.FeatureCollection("ft:1zRUOJL1LYCPJj-mjP6ZRx8sxYKNH8EwDw3EPP66K");
var modisNDVI = ee.ImageCollection("MODIS/MCD43A4_006_NDVI").filterDate('2015-01-01', '2015-03-15');

// create dummy image.
// var stacked_image = ee.Image();

// create function to combine all images into one image as bands.
// var combine = function(img, stack){
//  stack = ee.Image(stack);
//  return stack.addBands(img.select([0], [img.get('system:index')]));
//};

var rename_band = function(img){
  return img.select([0], [img.id()]);
};

// stack all the images into a single image.
stacked_image = modisNDVI.map(rename_band).toBands(); //iterate(combine, stacked_image);

// determine scale to perform reduceRegions.
var scale = modisNDVI.first().projection().nominalScale();

// calculate the timeseries for each feature.
var ts = ee.Image(stacked_image).reduceRegions({collection: regions, reducer: ee.Reducer.mean(), scale: scale});

// print results.
print(ts);

edit: edited to use "toBands()" instead of iterating using a user-defined function (now commented out) as suggested by Kuik in comments and here Making stack from many images in Google Earth Engine?

  • 2
    You'd better use toBands() to perform the operation you created a function for: gis.stackexchange.com/questions/300738/… – Kuik Nov 6 '18 at 12:50
  • This is close to what I need. However it now calculates the mean NDVI for each day per region. I only need the mean NDVI for each month for each region. – Vindicare Nov 8 '18 at 15:05

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.