1

All this gee is new for me. I'm trying to flatten and export a table resulting from reduceRegions. The resulting json is a FeatureCollection but trying to .flatten() will thrown an error.

// Import WDPA dataset
var dataset = ee.FeatureCollection('WCMC/WDPA/current/polygons');

//var roi = dataset.filter(ee.Filter.eq('WDPAID', 33046)); // Cacheu
var roi = dataset.filter(ee.Filter.eq('PARENT_ISO', 'GNB')).select('WDPAID'); // all PA in GNB

// Import Global Forest Change dataset.
var dataset = ee.Image('UMD/hansen/global_forest_change_2019_v1_7').clip(roi);

// Subset the loss year layer; make units absolute (instead of years since 2000). 
var treeLoss = dataset.select('lossyear').add(2000).selfMask();

// Display year of forest loss detection to the map.
Map.setOptions('SATELLITE');
Map.addLayer(treeLoss, {
    min: 2001,
    max: 2019,
    palette: ['0D0887', '5B02A3', '9A179B', 'CB4678',
              'EB7852', 'FBB32F', 'F0F921']
  }, 'Tree loss year');


var forestloss = treeLoss.reduceRegions({
  'collection': roi,
  'reducer': ee.Reducer.frequencyHistogram(),
  'scale': 100,
  'crs': 'EPSG:5070'})
  .select('histogram');

This went well with a single feature in my roi but but when I try to use a featurecollection and add a .flatten() at this point, I get an error

"the input collection must be a collection of collections but the element ... was feature, which is not a collection."

print(forestloss, 'forestloss');

Map.setOptions('SATELLITE');
Map.centerObject(roi)
Map.addLayer(roi, {}, 'WDPA GB', true);

link to code.

Any help will be much appreciated.

[EDITED] works fine with a single feature but not with a collection of features

Paulo E. Cardoso
  • 5,778
  • 32
  • 42
  • You currently have a collection of one feature, which will work fine in a table export. Could you [edit] your question to explain what you're trying to accomplish with `.flatten()`? What further processing or reformatting are you trying to achieve? – Kevin Reid Jun 09 '20 at 02:54
  • thank you @KevinReid. edited. it will fail when I have a collection of Features. I just want the histogram table for each feature from WDPA out as a csv file for plotting. – Paulo E. Cardoso Jun 09 '20 at 08:23

1 Answers1

3

.flatten() does only one thing: convert a feature collection of feature collections into a feature collection of those collections. In your case, you have a feature collection (the output of reduceRegions) which contains plain features, but each of those features has a property which is a dictionary.

In order to convert that to multiple features (rows in your exported table), you need to first map over the collection to convert the dictionary to a collection of features, and then flatten the collection.

var forestLossCollection =
  treeLoss.reduceRegions({
    'collection': roi,
    'reducer': ee.Reducer.frequencyHistogram(),
    'scale': 100,
    'crs': 'EPSG:5070'
  })
  .map(function (lossInRegionFeature) {
    // Get the histogram dictionary from the feature produced by reduceRegions.
    var forestLossDict = ee.Dictionary(lossInRegionFeature.get('histogram'));

    // Make a FeatureCollection out of the dictionary.
    return ee.FeatureCollection(
      forestLossDict
        .map(function (key, value) {
          // Construct a feature from the dictionary entry.
          return ee.Feature(null, {
            'system:index': key,
            'WDPAID': lossInRegionFeature.get('WDPAID'),
            'year': key,
            'loss': value});
        })
        // dict.map() returns a dictionary with newly computed values;
        // we just want the values in a list, to make a collection of.
        .values());
  })
  // Flatten the collection of collections returned by the map().
  .flatten();



print(forestLossCollection);

Export.table.toDrive({
  collection: forestLossCollection,
  fileNamePrefix: 'forestLoss',
  fileFormat: 'csv',
  selectors: ['WDPAID', 'year', 'loss'],
});

https://code.earthengine.google.com/2bcfd3d34fed5255e25d5a553558de36

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
  • thank you for the very detailed example. In fact I was trying to get annual loss for every single feature from the WDPA dataset and not only the first (or any other captured with WDPAID). I suppose reduceRegions will be necessary. – Paulo E. Cardoso Jun 09 '20 at 23:08
  • 1
    @PauloE.Cardoso Ah, yes, reduceRegions is better then. You will then want to `.map()` over the result of reduceRegions to produce a collection and then `flatten` _that_ result. I'll see about a revised answer later — the weather's too hot to think in right now… – Kevin Reid Jun 10 '20 at 00:21
  • 1
    @PauloE.Cardoso I've updated my answer — I think it should address your actual problem now. – Kevin Reid Jun 11 '20 at 16:31