var aoi = ee.FeatureCollection("users/jrobertsonpanthera/surveyed_grid_3test")

// Hansen Data
var gfc = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')
var lossImage = gfc.select(['loss'])
var lossAreaImage = lossImage.multiply(ee.Image.pixelArea())

var lossYear = gfc.select(['lossyear'])

var lossByYearCollection = lossAreaImage
    collection: aoi, 
    reducer: ee.Reducer.sum().group({groupField: 1}),
    scale: 30
var stats = lossByYearCollection
  .map(function (feature) {
    var id = feature.get('id')
    var groups = ee.List(feature.get('groups'))
    return ee.FeatureCollection(groups.map(function(el) {
      var d = ee.Dictionary(el)
      return ee.Feature(feature.geometry(), {
        id: id,
        year: ee.Number(d.get('group')).format("20%02d"), 
        area: d.get('sum')


  collection: stats, 
  description: 'loss-area-by-polygon-and-year', 
  selectors: ['id, year, area'] // If don't want the .geo and system:index columns

//show aoi, zoom the map
Map.addLayer(ee.Image().paint(aoi, 1, 3), null, 'region'); 

//show the loss layer
var treeLossVisParam = {
  bands: ['lossyear'],
  min: 0,
  max: 1,
  palette: ['yellow', 'red']
Map.addLayer(gfc, treeLossVisParam, 'tree loss year');

In the code above (and here), I have a grouped reducer that is getting the annual mean value from the yearloss band of the Hansen Forest Change dataset, mapping over a feature collection, and outputting a CSV as shown below. There is a row for each year (2000-2022) and the associated id of each vector feature in the FC:

Printed FeatureCollection:

enter image description here

Output CSV:

values in rows

I'm trying to transpose this data so that have a row for each id and columns for each year of data:

enter image description here

I've had success with this when mapping over an image collection with bands for each year, with something like this:

var AnnualImg = ee.ImageCollection(ICAnnual.iterate( 
  function (image, previous) {
    return ee.Image(previous).addBands(image);
var FCReduced = ee.Image(AnnualImg) 
      collection: aoi,
      reducer: ee.Reducer.mean(),
      scale: 463.313,
      crs: 'EPSG:4326',

but I'm struggling to change this format of the FeatureCollection so my CSV has columns instead of rows for each year. What am I missing about how this grouped reducer differs?


1 Answer 1


In this case, you might want to map over the aoi collection and use reduceRegion() instead of using reduceRegions(). Then it's a matter of fiddling to turn years into columns - I don't know a very simple way to do this. I tend to turn the data into an array and transpose it.

var stats = aoi.map(function (feature) {
  var tuples = ee.List(lossAreaImage
      reducer: ee.Reducer.sum().group({groupField: 1}),
      geometry: feature.geometry(),
      scale: 30,
      maxPixels: 1e13
  ).map(function (group) {
    group = ee.Dictionary(group)
    var year = group.getNumber('group').add(2000)
    var area = group.getNumber('sum')
    return [year, area]
  var yearsAreas = ee.Array(tuples).transpose()
  var years = yearsAreas
    .slice(0, 0, 1)
    .map(function (year) {
      return ee.Number(year).format('loss_%d')
  var areas = yearsAreas
    .slice(0, 1)
  return ee.Feature(feature.geometry(), ee.Dictionary.fromLists(years, areas))
    .set('id', feature.get('id'))


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.