3

I have an ImageCollection that I made calculation with so that it now contains images that show a ratio of one band within a given Polygon. I would like to get the mean and standard deviation for each image of the collection within the polygon, so I have a value for each image afterwards. I keep on receiving the error of ReduceRegion not working for all the codes I am trying. Maybe you can help me to understand this better and solve the problem.

I tried this code for example:

I edited code but unfortunately still the same error. I read it could be because of null values but I do have a function sorting out null values so that shouldn't be the issue

var reducers = ee.Reducer.mean().combine({
  reducer2: ee.Reducer.stdDev(),
  sharedInputs: true
});

function stats (image) {
  var stats1 = image.reduceRegion({
    reducer: reducers,
    geometry: MODISofstation,
    scale: 30,
    bestEffort: true
  });
  return image.set(stats1);

var statistics = ImageCollection.map(stats);
print (statistics);
1
  • I fixed your issues in my answer by using the same script of your previous question. It works as you expected.
    – xunilk
    Mar 29, 2021 at 1:47

2 Answers 2

1

I completed with your snippet code my script used in your previous question as follows:

var maskL8 = function(image) {
  var qa = image.select('BQA');

  var mask = qa.bitwiseAnd(1 << 4).eq(0);
  return image.updateMask(mask);
};

var pt = ee.Geometry.Point([-1.869490554037725, 41.191353356841205]);

var polygon = ee.Geometry.Polygon(
        [[[-1.8966130515963187, 41.18786546760974],
          [-1.8736104270846, 41.173136775751885],
          [-1.8413380882174124, 41.176754656054],
          [-1.8389348289400687, 41.19974936510326],
          [-1.861250807943975, 41.207498570723196],
          [-1.8732671043306937, 41.19690775979286],
          [-1.8883733055025687, 41.2000076867413]]]);

Map.addLayer(pt);
Map.centerObject(pt);

var start = '2017-01-01';
var finish = '2017-06-01';

var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
  .filterDate (start,finish)
  .filterBounds(pt)
  .filter("WRS_ROW <= 122")
  .map(maskL8);

var myB8 = l8.select("B8");

//receiving the values at pt for each image

var getB8 = function(image) {

  // Reducing region and getting value
  var value_B8 = ee.Image(image)
    .reduceRegion(ee.Reducer.first(), pt)
    .get('B8');

  return value_B8;
};

var count = myB8.size();

var listOfImages = l8.toList(count);

var B8_list = listOfImages.map(getB8);

print("B8 list", B8_list);

var nonNulls = B8_list.filter(ee.Filter.neq('item', null));

print("Non Null Values", nonNulls);

var idxList = nonNulls.map(function extract (ele) {
  
  var idx1 = nonNulls.indexOf(ele);
  
  var idx2 = B8_list.indexOf(nonNulls.get(idx1)); 
  
  return idx2;
  
});

print("Indices of Non Null Values", idxList);

//Ratio function

var RatioALL = idxList.map(function  calculateRatio (ele) {
  
  var idx = ele;

  var value = ee.Number(B8_list.get(idx));
  
  var image = listOfImages.get(idx);
  
  var ratio1 = ee.Image(image).select('B8')
                              .clip(polygon)
                              .divide(value);

  var time = ee.Image(image).get('system:time_start');

  return ratio1.set('system:time_start', time);
  
});

print("Original Image Collection", myB8);

print ("Ratio All for Non Null Values", RatioALL);

var getStats = function(image) {
  
  var reducers = ee.Reducer.mean().combine({
  reducer2: ee.Reducer.stdDev(),
  sharedInputs: true
  });

  var stats1 = ee.Image(image).reduceRegion({
    reducer: reducers,
    geometry: polygon,
    scale: 30,
    bestEffort: true
  });
  
  return ee.Image(image).set(stats1);

};

var statistics = RatioALL.map(getStats);

print("statistics", statistics);

After running it in GEE code editor, I got expected result; as it can be observed in following image:

enter image description here

2
  • That works perfectly, thank you so much!
    – xdsccc
    Mar 29, 2021 at 8:52
  • You're welcome.
    – xunilk
    Mar 29, 2021 at 11:22
1

When you map over collections, you have to return something that can go back into a collection. Dictionaries can't do that. Instead, put the stats on the image and return that:

function stats (image) {
  var stats1 = image.reduceRegion({
    reducer: reducers,
    bestEffort: true,
  });
  return image.set(stats1);
}

Also, you need to specify your polygon in the reduceRegion and probably a scale.

1
  • I edited the code in the original post but it still gives me a "image.reduceRegion is not a function"
    – xdsccc
    Mar 28, 2021 at 14:11

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.