1

I want to write a function that takes class id and number of points for each class as argument and samples points from polygons, returning a FeatureCollection.

I could only write a function that samples the same number of points [100 points in the example] for each class with iteration as below:

GEE Link: Reproducible GEE Example

Let me know if you can't open the polygon file

// Reproducible Example for Training Point Sampling

// Create id List
var idList = ee.List.sequence(11, 13).map(function(x) {return ee.Number(x)});

// Extraction Function
var collectTrain = function(id, featureCol) {
  // cast
  id = ee.Number(id);
  featureCol = ee.FeatureCollection(featureCol);
  // Extract
  var point = ee.FeatureCollection.randomPoints(
   polygons.filter(ee.Filter.eq('id', id)), 100)
   .map(function(feat){
      feat = ee.Feature(feat);  
      return feat.set('id', id);  
   });
  
  return featureCol.merge(point);
};

// Initial FeatureCollection
var point = ee.FeatureCollection.randomPoints(
   polygons.filter(ee.Filter.eq('id', 11)), 1)
   .map(function(feat){
      feat = ee.Feature(feat);  
      return feat.set('id', 11);  
   });

//Iterate over idList starting from the initial point
var training = ee.FeatureCollection(idList.iterate(collectTrain, point));
print(training);

How could we write such a function that takes two lists as arguments, such as in R with purrr::map2 and works with iterating those two lists. Arguments should be like:

id = [11, 12, 13]
point = [100, 150, 120]
2
  • 1
    I cannot open the polygon file. Please click on the asset, click share and turn on the "anyone can read" option.
    – kkrao
    Jun 20, 2020 at 18:35
  • I turned it now, thanks didn't know that. Jun 20, 2020 at 20:53

1 Answer 1

1

It is explained here by Gorelick:

Stratified random sampling with Google Earth Engine Error

We need to use stratifiedSample. Editing Gorelick's answer:

GEE Example

// Reproducible Example for Training Point Sampling - ClassBand

// Converting tables to FeatureCollection
var polygonsF = ee.FeatureCollection(polygons);

// Creating Class Image
var classes = ee.Image().byte().paint(polygonsF, "id").rename("class").toUint8();

// Sampling from Class Image - Returns FeatureCollections
var stratified = classes.addBands(ee.Image.pixelLonLat())
    .stratifiedSample({
      numPoints: 10, // This will be overridden by ClassValues & ClassPoints 
      classBand: 'class',
      projection: 'EPSG:32635',
      scale: 10,
      region: polygons,
      classValues: [11, 12, 13],
      classPoints: [100, 150, 120]
    }).map(function(f) {
      return f.setGeometry(ee.Geometry.Point([f.get('longitude'), f.get('latitude')]));
    });

print(stratified);

However, I couldn't find a way to restrict sampling only on some classes with this approach. You have to sample from all classes and then filter from them as:

// Sampling from Class Image - Returns FeatureCollections
var stratified = classes.addBands(ee.Image.pixelLonLat())
    .stratifiedSample({
      numPoints: 10, // This will be overridden by ClassValues & ClassPoints 
      classBand: 'class',
      projection: 'EPSG:32635',
      scale: 10,
      region: polygons,
      classValues: [11, 12],  // This will not throw id=13 out
      classPoints: [100, 150] // 10 points will be sampled from id=13
    }).map(function(f) {      // as defined in 'numPoints'
      return f.setGeometry(ee.Geometry.Point([f.get('longitude'), f.get('latitude')]));
    }).filter(ee.Filter.inList('class', [11, 12])); // getting desired Class

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.