2

I have a feature collection of polygons that contains a property ("yrbegun") indicating the year I want to use to do some manipulation. I would like to start a loop from the year before to the year after, i.e. if the property indicates 2005, I want to loop from 2004 to 2006

// Determine the year the project was started 
var projectyear = ee.Number(inFeature.get("yrbegun"))

// Define the "boundaries" of the loop
var startyear = projectyear.subtract(1)
var endyear = projectyear.add(1)

// Run the loop
for (var yr= projectyear; yr <= endyear; yr = yr + 1) {

  print('This is year ' + yr)
  print(yr)

}

However, the loop never runs. I tried to define projectyear without the ee.Number() function, but it also does not work.

2
  • Can you give some context for why you want to loop over years? For example, are you trying to create a moving window over time to smooth the data? Looping is often not the best approach, but it is hard to suggest a better approach without knowing more about what you are trying to do. Jul 19, 2017 at 1:37
  • Exactly. For each feature with year property x, I want to calculate certain band statistics for the years x-1, x, and x+1 and then write back the output into a new feature. The final output should be a new feature collection with three properties each containing these three calculated values Jul 20, 2017 at 10:08

2 Answers 2

7

You have to read and understand this before you start coding in GEE: https://developers.google.com/earth-engine/client_server

You are trying to execute a client side loop using a server side object (ee.Number). That is impossible.

You have 3 options: (I set projectyear to 2000 just to illustrate)

client side:

var projectyear = 2000
var startyear = projectyear - 1
var endyear = projectyear + 1

// Run the loop
for (var yr= projectyear; yr <= endyear; yr = yr + 1) {

  print('This is year ' + yr)
  print(yr)
}

server side: (can't print because it is a client side function)

var projectyear = ee.Number(2000)

// Define the "boundaries" of the loop
var startyear = projectyear.subtract(1)
var endyear = projectyear.add(1)

var seq = ee.List.sequence(startyear, endyear)

var result = seq.map(somefunction)

mixed (not recommended):

// Determine the year the project was started
var projectyear = ee.Number(2000)

// Define the "boundaries" of the loop
var startyear = projectyear.subtract(1)
var endyear = projectyear.add(1)


// Run the loop
for (var yr= projectyear.getInfo(); yr <= endyear.getInfo(); yr = yr + 1) {

  print('This is year ' + yr)
  print(yr)

}
4

Client-side looping is rarely the right approach when using Earth Engine, but it is usually possible to get equivalent results without loops. The following example creates a feature property that contains a range of years without client-side looping:

var myFeatures = ee.FeatureCollection([
  ee.Feature(ee.Geometry.Polygon([[[-108.9, 42.7],
               [-108.9, 42.6],
               [-108.8, 42.6]]]), {name:'poly1', yrbegun: 2014}),
  ee.Feature(ee.Geometry.Polygon([[[-108.7, 42.5],
               [-108.7, 42.4],
               [-108.6, 42.4]]]), {name:'poly2', yrbegun: 2015})  
]);

var addYearRange = function(feat) {
  var projectyear = ee.Date.fromYMD(
    ee.Feature(feat).get('yrbegun'), 1, 1
  );
  // Add a year range property.
  feat = feat.set('year_range', ee.List([
    projectyear.advance(-1, 'year'),
    projectyear,
    projectyear.advance(1, 'year')  
  ]));
  return feat;
};
var myFeaturesWithYearRange = myFeatures.map(addYearRange);

print('myFeatures', myFeatures);
print('myFeaturesWithYearRange', myFeaturesWithYearRange);

Similarly, if you want to create properties based on image statistics for each polygon (as indicated by your comment), you can add additional properties to the polygon:

var images = ee.ImageCollection('LANDSAT/LC8_SR');

feat = feat.set('mean_year_before',
  ee.Number(
      images.filterDate({
      start: projectyear.advance(-1, 'year'),
      end: projectyear
    }).mean()
      .reduceRegion({
        reducer: 'mean',
        geometry:feat.geometry(),
        scale:30,
        bestEffort: true
      }).get('B4')
  )
);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.