1

I am working with a multiband raster obtained from MODIS images and calculations between different periods. Every band contains the mean value of EVI index grouped by zones (using ee.reducer.mean().group()). I was able to export them as a single CSV, but I want to obtain a single CSV file where each column represents the grouped stats of every band. Is there any way to achieve this?

resultsStack is the multiband raster; filterZones is the grouping filter

for(var i = 0; i < 6; i++) {
      
      var stats = resultsStack.select(i).addBands(filterZones);
      
      var means = stats.reduceRegion({
      reducer: ee.Reducer.mean().group({
        groupField: 1,
        groupName: 'band_' + (i + 1).toString(),
      }),
      geometry: extent,
      scale: 500,
      maxPixels: 1e8
      });
        
      print(means);
      
      var asList = ee.List(means.get('groups')).map(function (pair) {
        return ee.Feature(null, pair);
      });
      
      var rawCollection = ee.FeatureCollection(asList);
      
      Export.table.toDrive({
        collection: ee.FeatureCollection(rawCollection),
        description: 'evi_band' + (i + 1).toString() + '_' + idate + '_' + fdate,
        folder: 'evi_stats_' + idate + '_' + fdate,
        fileFormat: 'CSV',
        selectors: ['band_' + (i + 1).toString(), 'mean']
      });
    }

1 Answer 1

1

There are plenty of options on how to do this. Unfortunately, as far as I know, they all require quite a bit of fiddling to get your data in the correct shape. Here's one way, creating a feature collection where every feature represent a band/group/mean. This collection is joined by itself on the group property, and a new collection where every feature contains all band means for a group.

var flatCollection = ee.FeatureCollection(
  resultsStack.bandNames()
    .map(function (band) {
      return ee.FeatureCollection(ee.List(
        resultsStack.select(ee.String(band))
          .addBands(filterZones)
          .reduceRegion({
            reducer: ee.Reducer.mean().group(1),
            geometry: extent,
            scale: 500,
            maxPixels: 1e8
          })
          .get('groups')
      )
      .map(function (group) {
        return ee.Feature(null, ee.Dictionary(group)).set('band', band)
      }))
    })
).flatten()


var stats = ee.Join.saveAll('features')
  .apply({
    primary: flatCollection.distinct('group'), 
    secondary: flatCollection, 
    condition: ee.Filter.equals({leftField: 'group', rightField: 'group'})
  })
  .map(function (groupFeature) {
    return ee.Feature(ee.List(groupFeature.get('features'))
      .iterate(
        function (feature, acc) {
          feature = ee.Feature(feature)
          return ee.Feature(acc)
            .set(feature.getString('band'), feature.getNumber('mean'))
        },
        ee.Feature(null, {group: groupFeature.getNumber('group')})
      )
    )
  })
  .sort('group')

https://code.earthengine.google.com/8e4b60811fd8864bce876bacfe2dcd70

You can implement this with a single reduceRegion() call, using repeat() on the reducer. I believe that would require you to use an unweighted mean reducer, but that might not a big problem. I'm not sure you'd see any performance improvements though. It could be worth to test if your performance isn't good enough when doing multiple reduceRegion() calls.

https://code.earthengine.google.com/9388e923cf5ab54943102c1692fc892d

1
  • Daniel, both methods work as intended. I can't see any noticeable difference in performance. Thanks!
    – gtapko
    Commented Nov 15, 2022 at 15:48

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.