1

I have a feature collection with a number of properties, all numbers. I want to aggregate all features in the collection that have a property in common. For instance, I want to merge features that have the same date value, and I wish to sum up the values of all other fields in the resulting feature collection. For example, a dummy feature collection:

var feat_list = [
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-02', count:1}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-04', count:1}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-02', count:3}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-01', count:2})
]

Should become this:

[
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-02', count:4}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-04', count:1}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-01', count:2})
]

I have tried everything on planet Earth. I tried using dictionaries also, but when I try to check if a date is present in two dictionaries or not using .contains() and && operator it doesn't produce Boolean values correctly.

1
2

You can use a .distinct() and ee.Join.saveAll(). It's a bit wordy, but it will be efficient for large collections, compared to other options.

var collection = ee.FeatureCollection([
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-02', count:1, x:1}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-04', count:1, x:1}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-02', count:3, x:0}),
  ee.Feature(ee.Geometry.Point(77.58, 13), {date:'2020-10-01', count:2, x:0})
]);

var propertiesToReduce = ['count', 'x'];

// We need one reducer for each property being summed.
// We could do this in a loop, but in case there is a property that *isn't*
// being summed (where you want e.g. the mean), writing it out is more flexible.
// This must have exactly as many combined reducers (or more precisely, exactly
// as many inputs) as propertiesToReduce.
var reducer = ee.Reducer.sum().setOutputs(['count'])
  .combine(ee.Reducer.sum().setOutputs(['x']));

var merged = ee.Join.saveAll('matches')
  .apply(
    collection.distinct('date'),  // We only want one date (don't care which).
    collection, ee.Filter.equals({leftField: 'date', rightField: 'date'}))
  .map(function (joinFeature) {
    // Prepare a collection of all the features with the same date.
    // (ee.Join.saveAll gives us a list by default.)
    var matches = ee.FeatureCollection(ee.List(joinFeature.get('matches')));
    return joinFeature
      // Keep only the date property unmodified; everything else will be
      // put back via the reducer.
      .select(['date'])
      // Sum the matches' properties using reduceColumns, and add that to the
      // single feature's properties using setMulti.
      .setMulti(matches.reduceColumns(reducer, propertiesToReduce));
  });

print(merged);

https://code.earthengine.google.com/c87d8fd993925712c94cb1f1821dee4a

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.