Google Earth Engine – Combining Grouped Reducers

google-earth-engineland-coverreducers

In Earth Engine, one can easily apply a same reducer to multiple band in an image. Unfortunately, it seems that this nice feature breaks if one uses a grouped-reducer?

repeat() will work if one seeks to apply the reducer with the same grouping variable on different variables. However, if one wants to apply the reducer on the same variable but with different combining variables (a very typical case for a multi-year land cover area counting), I can't figure out how to use combine? I know I could map the grouped reducer for each band, but this would be quite inefficient as the costly reducing operation would be repeated many times, instead of doing the reducing once with many functions.

Here is a test case: compute area of each forest class for multiple year using the vanCutsem forest data. I've tried so far:

  • ee.Reducer.sum().group(1).combine(ee.Reducer.sum().group(2), "secondReducer"), but will give: Reducer.group: Reducer.group groupField out of range

Code (see https://code.earthengine.google.com/fd81c997990d6d200913c346c379d40f):


var geometry =  ee.Geometry.Polygon([[[104.4176, -3.56098],[104.4176, -3.85425],[105.1152, -3.85425],
          [105.1152, -3.56098]]]);

/// Load data
var tmf_annual = ee.Image(ee.ImageCollection('projects/JRC/TMF/v1_2020/AnnualChanges').
  filter(ee.Filter.eq("system:index", "AnnualChangesASIA")).
  first())
  var pixel_area_img = ee.Image.pixelArea().divide(1000000).rename("area")  
var input = pixel_area_img.addBands(tmf_annual)

/// One single grouping variable: ok!
var sums = input.select(["area", "Dec1990"]).reduceRegion({
  reducer: ee.Reducer.sum().group({
    groupField: 1}),
  geometry: geometry,
  scale: 1000,
  maxPixels: 1e8
});

print(sums.get("groups"), "means 90")


/// PROBLEM: many  single grouping variable!?
var sums_many = input.select(["area", "Dec1990", "Dec1991"]).reduceRegion({
  reducer: ee.Reducer.sum().group(1).
    combine(ee.Reducer.mean().unweighted().group(2), "second"),
  geometry: geometry,
  scale: 1000,
  maxPixels: 1e8
});

print(sums_many)

Best Answer

As mentioned about this same post on the Earth Engine User's Group, grouped reducers need 2 inputs, but there's no way to share only one of those inputs with other reducers. To accomplish your task, you need to either replicate and interleave the area image so there are 30 pairs of landcover+area bands and repeat a simple grouped reducer 30 times, or you can just map over the years and run a simple 2-input reducer for each year + the area band. The cost & runtime of those should be essentially identical, since almost all of the time will be spent in fetching the landcover tiles.

Related Question