1

I have a featureCollection that contains a string property called 'TaxOrder'. In total there are 12 different possible TaxOrders (['Alfisols', 'Andisols', 'Aridisols', ...]).

I want to add the number of each TaxOrder (i.e. a number between 1 and 12) to each feature relative to the TaxOrder, e.g. if the TaxOrder is 'Alfisols', add {taxOrderNum: 1} as a property.

I've figured out a very lengthy way of doing this, so I am thinking there must be a simpler way of doing it, using .remap() for example (but without actually replacing the values of an existing property).

// Remove areas with null TaxOrder
USDA_Soils = USDA_Soils.filterMetadata('TaxOrder', 'not_equals', '');
print(USDA_Soils.limit(100));

// Function to add number corresponding to tax order
var addTaxOrderNum = function(feat) {
  var result = ee.Algorithms.If({
    condition: ee.String(feat.get('TaxOrder')).equals('Alfisols'),
    trueCase: feat.set({taxOrderNum: 1}),
    falseCase: ee.Algorithms.If({
      condition: ee.String(feat.get('TaxOrder')).equals('Andisols'),
      trueCase: feat.set({taxOrderNum: 2}),
      falseCase: ee.Algorithms.If({
        condition: ee.String(feat.get('TaxOrder')).equals('Aridisols'),
        trueCase: feat.set({taxOrderNum: 3}),
        falseCase: ee.Algorithms.If({
          condition: ee.String(feat.get('TaxOrder')).equals('Entisols'),
          trueCase: feat.set({taxOrderNum: 4}),
          falseCase: ee.Algorithms.If({
            condition: ee.String(feat.get('TaxOrder')).equals('Gelisols'),
            trueCase: feat.set({taxOrderNum: 5}),
            falseCase: ee.Algorithms.If({
              condition: ee.String(feat.get('TaxOrder')).equals('Histosols'),
              trueCase: feat.set({taxOrderNum: 6}),
              falseCase: ee.Algorithms.If({
                condition: ee.String(feat.get('TaxOrder')).equals('Inceptisols'),
                trueCase: feat.set({taxOrderNum: 7}),
                falseCase: ee.Algorithms.If({
                  condition: ee.String(feat.get('TaxOrder')).equals('Mollisols'),
                  trueCase: feat.set({taxOrderNum: 8}),
                  falseCase: ee.Algorithms.If({
                    condition: ee.String(feat.get('TaxOrder')).equals('Oxisols'),
                    trueCase: feat.set({taxOrderNum: 9}),
                    falseCase: ee.Algorithms.If({
                      condition: ee.String(feat.get('TaxOrder')).equals('Spodosols'),
                      trueCase: feat.set({taxOrderNum: 10}),
                      falseCase: ee.Algorithms.If({
                        condition: ee.String(feat.get('TaxOrder')).equals('Ultisols'),
                        trueCase: feat.set({taxOrderNum: 11}),
                        falseCase: ee.Algorithms.If({
                          condition: ee.String(feat.get('TaxOrder')).equals('Vertisols'),
                          trueCase: feat.set({taxOrderNum: 12}),
                          falseCase: feat
                        })
                      })
                    })
                  })
                })
              })
            })
          })
        })
      })
    })
  });
  return result;
};

// Map function over featureCollection
var USDA_Soils_Final = USDA_Soils.map(addTaxOrderNum);
print(USDA_Soils_Final.limit(100));

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

2 Answers 2

1

A general rule for this kind of problem is to express your repetitive structure as data, not code. A mapping from one value to another is a kind of data that can be stored in a dictionary.

So, first define a dictionary. (This can be done more cleverly to not have to list the numbers explicitly, but let's keep things simple.)

var taxOrders = ee.Dictionary({
  'Alfisols': 1,
  'Andisols': 2,
  'Aridisols': 3,
  'Entisols': 4,
  'Gelisols': 5,
  'Histosols': 6,
  'Inceptisols': 7,
  'Mollisols': 8,
  'Oxisols': 9,
  'Spodosols': 10,
  'Ultisols': 11,
  'Vertisols': 12,
});

Then, use that dictionary inside the feature mapping function.

var addTaxOrderNum = function(feature) {
  var taxOrderNum = taxOrders.get(feature.get('TaxOrder'));
  return feature.set('taxOrderNum', taxOrderNum);
};

https://code.earthengine.google.com/423c5b4f30b3928c57b8ec9413912bf2

0
1

One way of doing the same procedure, but with less code would be to first get all the distinct entries of 'TaxOrder' and order them in alphabetical order. Then, you can map a function to each Feature in the FeatureCollection, in order to return the index number of the 'TaxOrder' entry + 1 (as indices are zero-based).

// Get TaxOrder entries as a list
var listUnique = USDA_Soils.aggregate_array('TaxOrder')
                          // eliminate duplicates
                           .distinct()
                          // order in alphabetical order 
                           .sort();
print(listUnique);

var USDA_Soils_Final = USDA_Soils.map(function(feat){
  // Get String of TaxOrder 
  var featTax = feat.getString('TaxOrder');
  // Get index of featTax and add 1, as the indices are zero based
  var index = ee.Number(ee.List(listUnique).indexOf(featTax)).add(1);
  
  // Add the index as a property to each feature
  return feat.set({'taxOrderNum': index});
});

print('USDA_Soils_Final ',USDA_Soils_Final .limit(50));
1
  • Thanks for your answer! Unfortunately Kevin's was more concise, but I appreciate the effort!
    – M. Nicolas
    Commented Feb 8, 2022 at 22:54

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.