I am trying to calculate the average nighttime radiance of forested areas in South Asia and Southeast Asia, broken up by country and year, then export the results as a single table where each row is a different country and each column is a different year. I have a program that will make a separate feature collection for each year, but I need some way to combine them all together as different columns of one table.
Currently, this code creates 8 different export tasks (1 for each year). Each task produces a table with 16 rows (1 for each country) and a single column. I would like it to instead create a single task, which would produce a table with 16 rows and 8 columns.
var asia = ["Sri Lanka","Bangladesh","India","Afghanistan",
"Pakistan","Bhutan","Nepal","Cambodia","Indonesia", "Burma",
"Laos","Malaysia","Philippines","Singapore","Thailand","Vietnam"];
var countries = ee.FeatureCollection("USDOS/LSIB/2017");
var asiafeatures = asia.map(function(element){ // feature collection of country names
return ee.Feature(null, {'country': element});
})
// initialize table
var table = ee.FeatureCollection(asiafeatures);
var years = ee.List.sequence(2014, 2021); // list of numbers 2014 to 2021
var fields = years.map(function (number) {
return ee.String(number).slice(0, 4); // count only pixels with values of 0, 1, 2, or 3
})
var size = years.length()
var covers = ee.ImageCollection.fromImages( // assemble an image collection from images
years.map(function (y) { // for each year
return ee.ImageCollection("MODIS/061/MCD12Q1") // from the modis land cover image
.select('LC_Type1') // select this field
.filter(ee.Filter.calendarRange(y, y, 'year')) // filter it by the desired timespan
.median() // find the median
.set('year',y); // and set the value of the year field?
}).flatten()); // flatten the MODIS collection to 1 image
var rads = ee.ImageCollection.fromImages( // assemble an image collection from images
years.map(function (y) { // for each year
return ee.ImageCollection("NOAA/VIIRS/DNB/MONTHLY_V1/VCMSLCFG") // from the nightlight image
.select('avg_rad') // select this field
.filter(ee.Filter.calendarRange(y, y, 'year')) // filter by the desired timespan
.median() // find the median
.set('year',y);
}).flatten());
var coverslist = covers.toList(size); // turn the land cover image collection into a list of images, 1 per year
var radslist = rads.toList(size); // turn the nightlights image into a list of images, 1 per year
var sequence = ee.List.sequence(0, ee.Number(size).subtract(1)); // list of numbers from 0 to 7
var stats = sequence.map(function(seq){ // for each number in the sequence (each year)
return ee.FeatureCollection(asia.map(function(c){ // for each country in asia
var country = countries.filter(ee.Filter.eq('COUNTRY_NA', c)); // one country at a time
// country is a feature collection with 1 feature
var coverclipped = ee.Image(coverslist.get(seq)).clip(country); // grab an image from the list, serve it, clip
// you can't print this one because it's server-side, but it's an image
var coverclippedmasked = coverclipped.updateMask(coverclipped.lte(6)); // clip it to forest areas?
// still an image, still server-side
var binarymask = coverclippedmasked.selfMask().mask().clip(country).toInt(); // simplify to forest and not?
// yep
var vectors = binarymask.reduceToVectors({ // turn the mask into a polygon
geometry: country, // separated by country?
scale: 500,
maxPixels: 1e18
});
// vectors is a feature collection
var forestRadianceMed = ee.Image(radslist.get(seq)).reduceRegions({ // reduce the clipped nightlights by region
collection: vectors.filter(ee.Filter.eq('label', 1)), // forested polygons only
reducer: ee.Reducer.median(),
scale: 500
});
// forestRadianceMed is a feature collection
return ee.Feature(null, {}).set(ee.String(fields.get(seq)), forestRadianceMed.aggregate_mean('median'))
// this is a feature
}));
});
// this iterates through the list of computed objects and exports each collection individually
for(var i = 0; i < size.getInfo(); i++) {
Export.table.toDrive({
collection: stats.get(i),
description: years.get(i).getInfo() + '_forestRadianceMed',
selectors: [years.get(i).getInfo()]
})
}
// Well, it does the calculations, but they're still not all in one table.