So, I'm brand new to Google Earth Engine, and I've been trying for a while now to get my head around it. I'm aware of the limitations with iteration and the need to instead use the map() function, and the limitations with using if-checks, but I'm still struggling to adapt.

My goal is to obtain band values of lake-centers at a specific pixel that match to the sampling site AND sampling day that on site measurements were also taken, so I can compare the remote sensed value against the on-site measurements. The script below is just the relevant parts for this question and using some very small date/coordinate lists, but eventually this project will involve a MASSIVE list of coordinate pairs and sampling dates (Note - a specific site likely corresponds to multiple sampling days).


// Small sample of some dates to pull landsat images for
var DATES = ['2016-09-27', '2013-03-28', '2019-07-18', '2020-11-25', '2013-12-08'];

// Function to add a 'Date' column to datasets, for later filter purposes
var addTime = function(x) {
  return x.set('Date', ee.Date(x.get('system:time_start')).format("YYYY-MM-dd"))};

// Create an image collection from surface reflectance dataset consisting of only images from days that had sampling occur somewhere
var sitesCollection = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
            .filter(ee.Filter.eq('WRS_PATH', 16))
            .filter(ee.Filter.eq('WRS_ROW', 40));

// Confirm that just the desired images were extracted

// Small sample of some study sites sampled on those dates
var siteCoords_features = [
ee.Feature(ee.Geometry.Point(-81.9983,29.7035), {name: '2016-09-27 site'}),
ee.Feature(ee.Geometry.Point(-82.0169,29.6771), {name: '2013-03-28 site'}),
ee.Feature(ee.Geometry.Point(-82.0411,29.5299), {name: '2019-07-18 site'}),
ee.Feature(ee.Geometry.Point(-82.0186,29.6877), {name: '2020-11-25 site'}),
ee.Feature(ee.Geometry.Point(-81.8601,29.6201), {name: '2013-12-08 site'})];

// Creates a FeatureCollection from the list of coords
var pt_collection = ee.FeatureCollection(siteCoords_features);

// Two placeholder variables to allow for example pixel value extraction
var image = ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_016040_20150317');
var point = ee.Geometry.Point(-81.9983,29.7035); // Generate the pixel point for the sampled lake center to then pull pixel values from

// Print pixel value of band in the console... but for just one point, for just one image.
//  So obviously I want to put this in a function so I can map over a list with it, but I'm not sure how 
var pixelInfo = image.reduceRegion({
  geometry: point,
  scale: 30,
  reducer: ee.Reducer.mean()});
print('Band 1 (ultra blue) surface reflectance value', pixelInfo.get('B1'));

I'm guessing I'll need a function within a function here to iterate through the two lists, but I'm not sure how to set that up. Likewise, without the aid of if-checks to only pull values that match to my two variable lists, I'm even more lost on how to only get what I need. Normally this is where I'd set up a dictionary to house a date and location together, but again I don't know how I'd use if-checks with that to only pull what's needed. If it's not possible to specifically get all pixel values that match to date AND coordinates, I could just break the dataset into chunks by year perhaps (so I don't hit the query limit), and just pull from each image ALL the locations at once for every day ANY sampling was done, and then afterwards manually filter out the values that don't match to any performed samples.

1 Answer 1


Your guess seems to be right.. Based on your suggestions you probably need something like this:

var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
    .filterDate(startDate, endDate)
print(collection, 'collection')    

var outputData = pt_collection.map(function(feat){
  // only map over images that intersect with the selected feature.
  var filterCollect = collection.select(bandsToReduce).filterBounds(ee.Feature(feat).geometry())
  return filterCollect.map(function(img){
    return ee.Feature(null,img.reduceRegion({
      geometry: feat.geometry(),
      scale: 30,
      reducer: ee.Reducer.mean()})).set({ // ste additional properties
        name: feat.get('name'),
        lat: feat.geometry().coordinates().get(0),
        lon: feat.geometry().coordinates().get(1),
print(outputData, 'test')

But as you already pointed out, the if statements are a bit troublesome. You could apply a filter to the resulting outputData or use a ee.Algorithms.If(), but that might be troublesome if you go for A LOT of locations. See if this works for you!


  • That's a huge help, thanks! As I feared though, doing the all-sites-at-all-dates approach means I'd have to run the script over 100 times to capture all the data without triggering any query/memory limits within GEE. Would this filtering/if-algorithm approaches actually help skip over processing non-matching data entirely, to allow for processing more data at a time? Is there a way to at least skip over entries that have no band values, due to the cloud/shadow function deleting those pixels? New draft: code.earthengine.google.com/33310ddcfa0b77d0d652968f9a0e606b
    – randomTask
    Commented Jul 15, 2021 at 0:35
  • 1
    I'm guessing you are going to reach the GEE limits soon but I'm not sure. Related to optimizing your workflow i'd suggest asking A new question, because i'm not really sure what would actually result in 'better' performance. My suggestion would be to break the tasks consistently, e.g. per year and path/row combination or state an export your output as asset or check this question: gis.stackexchange.com/questions/403950/…
    – Jobbo90
    Commented Jul 15, 2021 at 7:11

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.