0

I'm trying to detect land use land cover (LULC) changes between 1990 and 2000 using the Copernicus Corine land cover maps in Google Earth Engine (GEE). However, I'm unable to find change maps in the GEE library. Additionally, my computer's storage and computational capacity is limited I don't want to use change maps of copernicus, so I've decided to prepare the LULC change map myself using the Corine maps from 1990 and 2000. My goal is to obtain the area of each LULC change pair (e.g. 111 to 121, 111 to 211, etc.).

However, when I run my code, I get the error message Line 38: Invalid argument specified for ee.Number(): 0,1. Can anyone help me figure out what's causing this error? Maybe downloading from copernicus website and uploading to GEE a good option to solve it but I am not sure.

Here's my code:

// Import necessary datasets
var corine_1990 = ee.Image("COPERNICUS/CORINE/V20/100m/1990");
var corine_2000 = ee.Image("COPERNICUS/CORINE/V20/100m/2000");
var gaul = ee.FeatureCollection("FAO/GAUL/2015/level1");

// Define region of interest (Ankara)
var ankara = gaul.filter(ee.Filter.eq('ADM1_NAME', 'Ankara'));

// Clip Corine maps to Ankara border
var corine_1990_ankara = corine_1990.clip(ankara);
var corine_2000_ankara = corine_2000.clip(ankara);

// Define land cover classification legend
var legend = {
  '111': 'Continuous urban fabric', '112': 'Discontinuous urban fabric', '121': 'Industrial or commercial units', '122': 'Road and rail networks and associated land', '123': 'Port areas', '124': 'Airports', '131': 'Mineral extraction sites', '132': 'Dump sites', '133': 'Construction sites', '141': 'Green urban areas', '142': 'Sport and leisure facilities', '211': 'Non-irrigated arable land', '212': 'Permanently irrigated land', '213': 'Rice fields', '221': 'Vineyards', '222': 'Fruit trees and berry plantations', '223': 'Olive groves', '231': 'Pastures', '241': 'Annual crops associated with permanent crops', '242': 'Complex cultivation patterns', '243': 'Land principally occupied by agriculture with significant areas of natural vegetation', '311': 'Broad-leaved forest', '312': 'Coniferous forest', '313': 'Mixed forest', '321': 'Natural grasslands', '322': 'Moors and heathland', '323': 'Sclerophyllous vegetation', '324': 'Transitional woodland-shrub', '331': 'Beaches - dunes - sands', '332': 'Bare rocks', '333': 'Sparsely vegetated areas', '334': 'Burnt areas', '335': 'Glaciers and perpetual snow', '411': 'Inland marshes', '412': 'Peat bogs', '421': 'Salt marshes', '422': 'Salines', '423': 'Intertidal flats', '511': 'Water courses', '512': 'Water bodies', '521': 'Coastal lagoons', '522': 'Estuaries', '523': 'Sea and ocean'
};

// Compute land cover change between 1990 and 2000
var change = corine_1990_ankara.neq(corine_2000_ankara);

// Compute area of each land use land cover type for each Corine map
var landcover_area_1990 = ee.Image.pixelArea().addBands(corine_1990_ankara).reduceRegion({
  reducer: ee.Reducer.sum().group(1),
  geometry: ankara.geometry(),
  scale: 100,
  maxPixels: 1e13
});

var landcover_area_2000 = ee.Image.pixelArea().addBands(corine_2000_ankara).reduceRegion({
  reducer: ee.Reducer.sum().group(1),
  geometry: ankara.geometry(),
  scale: 100,
  maxPixels: 1e13
});

// Compute area of land cover changes between 1990 and 2000
var class_pairs = ee.List(ee.Dictionary(ee.Image.pixelArea().addBands(change).reduceRegion({
  reducer: ee.Reducer.sum().group([0,1]),
  geometry: ankara.geometry(),
  scale: 100,
  maxPixels: 1e13
})).get('groups')).map(function(item){
  var keys = ee.List(item.get('group')).map(function(key){
    return ee.Number.parse(key);
  });
  var from_class = legend[keys.get(0)] || 'Unknown';
  var to_class = legend[keys.get(1)] || 'Unknown';
  return ee.Feature(null, {
    'From Class': from_class,
    'To Class': to_class,
    'Area (sq m)': ee.Number(item.get('sum')).round()
  });
});

// Export results as a CSV file
Export.table.toDrive({
  collection: ee.FeatureCollection(class_pairs),
  description: 'LULC_change_pairs',
  fileFormat: 'CSV'
});

1 Answer 1

2

You're passing an array to group() while it expects an integer. I think something like this could do what you're after:

var areas = ee.FeatureCollection(ee.List(
  ee.Image.pixelArea()
    .addBands(corine_1990_ankara)
    .addBands(corine_2000_ankara)
    .reduceRegion({
    reducer: ee.Reducer.sum().group(1, 'from').group(2, 'to'),
    geometry: ankara.geometry(),
    scale: 100,
    maxPixels: 1e13
  }).get('groups')).map(function (toGroup) {
    toGroup = ee.Dictionary(toGroup)
    return ee.List(toGroup.get('groups')).map(function (fromGroup) {
      fromGroup = ee.Dictionary(fromGroup)
      return ee.Feature(null, {
        'From Class': legend.get(fromGroup.getNumber('from').format('%d')),
        'To Class': legend.get(toGroup.getNumber('to').format('%d')),
        'Area (sq m)': ee.Number(fromGroup.get('sum')).round()
      })
    })
  }).flatten()
).filter(ee.Filter.notEquals({leftField: 'From Class', rightField: 'To Class'}))

https://code.earthengine.google.com/0ec8507daa1ca063c23aa06005958d1c

1
  • Thank you very much!
    – Gencergis
    Apr 11, 2023 at 16:51

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.