Looping a monthly mean NDVI over a list of years

I need to calculate mean NDVI on a year-parish level in Ecuador. Parishes are the finest level of governmental structure. I have written code (heavily based on this: https://knowyourspace.dk/2020/12/20/mean_ndvi_per_polygon_gee/) that outputs a csv table with the mean NDVIs per parish for one year, but I have no idea how to loop over multiple years.

My basic intuition was to create a list of years, make the code I have written into one big function, and map that big function over my list of years. That did not work, however.

I'd love help in figuring this out. Below is the code for one year. The shapefile can be found at: https://gadm.org/download_country.html.

``````// Define ecuador country borders for easier computation later on
var worldcountries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');

// Import parish level shape files and add to map
Map.setCenter(-85.33, -2 ,6);

// Set the date for one year (map over years later)
var year = '2019'
var startdate = year+'-01-01';
var enddate = year+'-12-31';

// Import image collection and filter accordingly
var landsat = ee.ImageCollection("LANDSAT/LC08/C02/T1_RT_TOA")
.filterDate(startdate,enddate);

// Add an NDVI band to the image collection and select that band
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
};

// Get the mean over each parish
var mean = landsatNDVI.mean().clip(parish);

// Map the meaned NDVI
var color = {
min: 0.0,
max: 1.0,
palette: [
'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
'66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
'012E01', '011D01', '011301'
],
};

// Add mean NDVI value to parishes in feature collection.
var MeanNDVIperParish = mean.reduceRegions({
collection: parish,
reducer: ee.Reducer.mean(),
scale: 30,
});

// Remove the content of .geo column for more pleasant .csv files
var NDVIfinal = MeanNDVIperParish.map(function(feat){
var nullfeat = ee.Feature(null)
return nullfeat.copyProperties(feat)
})

// Export the table
Export.table.toDrive({
collection: NDVIfinal,
folder: 'GEE',
fileFormat: 'CSV'
});
``````

You don't specify exactly how you want your output to be formatted. Here's one option that create an image where each year is a separate band, resulting in a CSV where each row is a perish and the mean for each year are in the columns:

``````var startYear = 2019
var endYear = 2020

var means = ee.Image(
ee.List.sequence(startYear, endYear)
.iterate(
function(year, acc) {
yearlyMeans(ee.Number(year))
)
},
ee.Image([])
)
)

var ndviPerParish = means.reduceRegions({
collection: parish,
reducer: ee.Reducer.mean().forEachBand(means),
scale: 30
})

var columns = ['Parish'].concat(sequence(startYear, endYear))

Export.table.toDrive({
collection: ndviPerParish.sort('Parish'),
description: 'ndviPerParish',
selectors: columns
})

function yearlyMeans(year) {
var startDate = ee.Date.fromYMD(year, 1, 1)

// You probably don't want to use a real-time collection for this.
// It would probably be better with TOA or the Level 2 collections
// Note that Level 2 require you to rescale the numbers before you take the normalized difference
// var landsat = ee.ImageCollection("LANDSAT/LC08/C02/T1_RT_TOA")
var landsat = ee.ImageCollection("LANDSAT/LC08/C02/T1_TOA")
.filterDate(startDate, endDate)

return image
.normalizedDifference(['B5', 'B4'])
.rename(year.format('%d')) // Rename NDVI band to the current year
}

}

// Create client-side sequence
function sequence(from, to) {
return Array.apply(null, {length: to - from + 1})
.map(function (_, i) {
return i + from
})
}
``````