Google Earth Engine – How to Create a Function or Loop to Import Training Data for Several Regions at Once

functiongoogle-earth-enginegoogle-earth-engine-javascript-apiloop

For several supervised classifications I want to assign training data from one feature collection to several regions, for which I have a quality mosaic each.
My dataset for the feature collection contains one attribute which defines, to which of my regions the training data belongs (attribute name "region") and of course I have one attribute "class".

To assign the training data for one region, I would just do the following:

//'LVha2' is the name of my image in the first region, 
//'training' is my feature collection which contains the training data in form of polygons, 
//'LVha-2' is the attribute value of the attribute 'region' in my feature collection 


var LVha2_px = LVha2.sampleRegions({
  collection: training.filter(ee.Filter.eq('region', 'LVha-2')),
  properties: ['class'],
  scale: 10
});

but as I have 17 regions, I would like to do this using a function or some kind of iteration to avoid spaghetti code.

I guess I might have to iterate over a list of the images and additionally over a list of region names how they are defined in the feature collection.

I tried sth. like this:

var label = "class";

// creating list of region names how they are defined in the FeatureCollection 
// (there are 17 but for testing I use just these two)
var regionNames = ["LVha-1", "LVha-2"];

// creating list of images ('LVha1' and 'LVha2' are two of my 17 images covering 17 regions)
var subsets = [LVha1, LVha2]

// Loop through both lists (which have same length) and assign variables 
//for the image and the corresponding features which are the training data

for (var i = 0; i < regionNames.length; i++) {
  var img = subsets[i]
  var region = regionNames[i]

// create a function to get the sample from the polygons FeatureCollection.
  function pixels(img) {
      return img.sampleRegions({
      collection: training.filter(ee.Filter.eq('Region', region)),
      properties: ['class'],
      scale: 10
    });}
}


//call the function for region 'LVha2'
var LVha2_px = pixels(LVha2)

it does not work, the feature collection 'LVha2_px' contains 0 elements. There are probably several flaws as I am new to using GEE. Is there a more efficient way of solving this than copying the code block from the beginning 17 times into my script?
I am aware one should not place a function in a for loop but I do not know how else to do it.

Best Answer

While I think your code might work with some minimal changes, here's an example that might help you structure what you want to do in a way that doesn't use a for loop:

// Images with a "region" property
var image1 = ee.Image.random(1).set({region:"region1"});
var image2 = ee.Image.random(2).set({region:"region2"});
var image3 = ee.Image.random(3).set({region:"region3"});

var imageList = ee.List([image1,image2,image3]); 

// The function to apply to one image
function pixels(img){
  return img.sampleRegions({
    collection: training.filter(ee.Filter.eq("region",img.get("region"))),
    properties:["class"],
    scale:100000 // I made the training polygons really big in this example. 
  })
}
// Testing the function
var test1 = pixels(image1);
print(test1) // FeatureCollection

// Mapping the function to all images -- 
// one option to loop over the images is the following:
var N = imageList.size();  // Number of images
var s = ee.List.sequence(0,N.subtract(1));// subtract 1 because it will be from 0 to N-1

var results = ee.FeatureCollection(s.map(function(n){
 return pixels(ee.Image(imageList.get(n)));
}
)).flatten();

print(results) // 40 features with properties "class" and "random"

Full example with a small set of training polygons:

https://code.earthengine.google.com/094a13ce16446721acb1221424671a6e

You have 17 images, so I think it is feasible to add a "region" property to them.