1

I am using S1 images and clustering in Google Earth engine to identify different land uses. I clustered using ee.Clusterer.wekaKMeans(5).train. Now I want to create a histogram that shows the area per cluster, but I don't know how. I have this code already but I get the following error Error generating chart: Reducer.group: Reducer.group groupField out of range. How do I solve this?

// ********************************************
// pre-processing
// ********************************************

var geometry_roi = 
    /* color: #d63000 */
    /* shown: false */
    ee.Geometry.Polygon(
        [[[124.545,8.165],[124.545,8.235],[124.565,8.275],[124.56,8.3],[124.585,8.32],[124.58,8.345],[124.605,8.44],[124.795,8.445],[124.795,8.495],[124.825,8.555],[124.83,8.585],[124.86,8.62],[124.935,8.61],[125.05,8.62],[125.25,8.62],[125.26,8.61],[125.265,8.41],[125.28,8.395],[125.285,8.375],[125.31,8.355],[125.31,8.34],[125.345,8.315],[125.35,8.27],[125.37,8.24],[125.37,8.175],[125.4,8.115],[125.41,8.005],[125.445,7.95],[125.465,7.755],[125.46,7.735],[125.45,7.73],[125.445,7.565],[125.43,7.555],[125.395,7.555],[125.375,7.53],[125.35,7.515],[125.29,7.51],[125.275,7.48],[125.26,7.47],[125.22,7.475],[125.21,7.485],[125.165,7.485],[125.17,7.46],[125.16,7.44],[125.135,7.43],[125.1,7.435],[125.085,7.415],[125.04,7.39],[125.02,7.39],[125.01,7.4],[124.955,7.395],[124.945,7.405],[124.92,7.395],[124.87,7.4],[124.855,7.43],[124.855,7.455],[124.875,7.495],[124.815,7.535],[124.81,7.55],[124.8,7.555],[124.785,7.61],[124.74,7.64],[124.725,7.685],[124.71,7.7],[124.71,7.73],[124.695,7.74],[124.685,7.77],[124.66,7.79],[124.65,7.815],[124.615,7.83],[124.6,7.875],[124.575,7.9],[124.595,7.96],[124.555,7.995],[124.55,8.04],[124.555,8.08],[124.54,8.1],[124.53,8.145],[124.545,8.165]]]);

var roi=geometry_roi;
Map.centerObject(roi);

var startDate = ee.Date('2019-01-01');
var endDate =  ee.Date('2020-12-31');

var sentinel1_vh = ee.ImageCollection('COPERNICUS/S1_GRD')
  .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VH'))
  .select('VH')
  .filter(ee.Filter.eq('instrumentMode', 'IW'))
  .filter(ee.Filter.eq('resolution_meters', 10))
  //.filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING'))
  .filter(ee.Filter.date(startDate, endDate))
  .filter(ee.Filter.bounds(roi));

// For month
var month = 1;
// Calculating number of intervals
var months = endDate.difference(startDate,'month').divide(month).toInt();
// Generating a sequence 
var sequence = ee.List.sequence(0, months); 
print(sequence)

var sequence_s1 = sequence.map(function(num){
    num = ee.Number(num);
    var Start_interval = startDate.advance(num.multiply(month), 'month');
    var End_interval = startDate.advance(num.add(1).multiply(month), 'month');
    var subset = sentinel1_vh.filterDate(Start_interval,End_interval);
    return subset.median().set('system:time_start',Start_interval);
});

var byMonthYearS1 = (ee.ImageCollection.fromImages(sequence_s1)).filter(ee.Filter.date(startDate, endDate));
var multibands1 = byMonthYearS1.toBands().clip(roi);

// Reset the bandnames
var namess1 = multibands1.bandNames();
print('bandnames',namess1)
// rename the bandnames 
var nMonthss1 =(namess1.length()).subtract(1) ;

var pertamas1=sentinel1_vh.first();
var systimes1=pertamas1.get('system:time_start');
var startDates1 =(ee.Date(systimes1));
// get a list of time strings to pass into a dictionary later on
var monLists1 = ee.List.sequence(0, nMonthss1).map(function (n) {
  return startDates1.advance(n, 'month').format('yyyy-MM');
})
var multibands1 = multibands1.rename(monLists1).clip(roi);//
var combinedband=multibands1;

// ********************************************
// clustering
// ********************************************

var training = combinedband.sample({
  region: roi,
  scale: 10,
  numPixels: 2000,
  tileScale:8
});

var clusterer = ee.Clusterer.wekaKMeans(5).train({
  features:training
});

// Cluster the input using the trained clusterer.
var result_cluster =combinedband.cluster(clusterer).byte();
var clusters = [0, 1, 2, 3, 4];
var values0 =   [1, 2, 3, 4, 5];

var remapped_cluster = result_cluster.remap(clusters, values0).clip(roi);//

// ********************************************
// visualise result
// ********************************************

var areaChart = ui.Chart.image.byClass({
  image: ee.Image.pixelArea().addBands(remapped_cluster),
  classBand: 'clustering', 
  region: roi,
  scale: 10,
  reducer: ee.Reducer.sum()
});

print(areaChart);

1 Answer 1

1

There is no band named "clustering" in your chart inputs. The remapped band of labels is named "remapped". But even fixing that, there are too many points in your ROI to use that chart helper. You'll need to run your own reduceRegion to get numbers to chart (or just use a larger scale):

var result = ee.Image.pixelArea().addBands(remapped_cluster).reduceRegion({
  reducer: ee.Reducer.sum().group(1),
  geometry: roi,
  scale: 10,
  maxPixels: 1e9
});

// Convert list of group dictionaries into a list of lists.
var groups = ee.List(result.get("groups")).map(function(group) {
  group = ee.Dictionary(group)
  return [group.get('group'), group.get('sum')]
})
// Add a header to the data table.
groups = groups.insert(0, ["Class", "Area"])

// Print the chart into a panel so we don't block the browser.
var panel = ui.Panel(ui.Label("Loading chart..."));
print(panel)
groups.evaluate(function(result) {
  panel.widgets().reset([ui.Chart(result).setChartType('ColumnChart')])
})

https://code.earthengine.google.com/73377925e6ebdaa317c4f6b037191181

1
  • Thank you so much Noel! Commented Oct 27, 2021 at 8:52

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.