3

Had a field that had some categories that didnt make sense to be listed alphabetically so wanted to add a preceding number to the text so they would be in the order I wanted. Ran it once and it worked on all but 1 of them so I thought maybe there was an extra space so went into the field to copy and paste the value. It was the same but I copied it anyway and then when I ran it again it caused the entire column to become null. Didnt have undo on so now have to go through the entire workflow. Why did this happen so I can avoid it in the future?

Expression:

func(!Hab_Class!)

Code Block:

def func(hab):
    if hab == 'Lowest':
        return '1. Lowest'
    elif hab == 'Marginal':
        return '2. Marginal'
    elif hab == 'Moderately High':
        return '3. Moderately High'
    elif hab == 'Highest':
        return '4. Highest'
1
  • There must be some value that your ifs doesnt catch. Add an else to and return something, for example hab. Or the function will return None. What is the field length?
    – BERA
    Jan 22 at 10:29

1 Answer 1

10

If you're calculating into the same column that you're getting values from, you always run the risk of losing/messing up the values in that column.

In your case, you'd already calculated the column, so hab values that had already been changed did not match anything in your if: elif: statement and because you didn't explicitly return anything your function automatically returned None (standard python behaviour) and ArcGIS duly set the values to None.

Your best way to avoid this is to add a temporary column, run your calculation to populate the temp column then check and if everything is ok, calculate the original column from the temp column.

There's also an 'enable undo' toggle in the field calculator tool, but I've never used that.

Alternatively, ensure your expression returns something instead of None:

Code Block:

def func(hab):
    if hab == 'Lowest':
        return '1. Lowest'
    elif hab == 'Marginal':
        return '2. Marginal'
    elif hab == 'Moderately High':
        return '3. Moderately High'
    elif hab == 'Highest':
        return '4. Highest'
    else:
        return hab  # leave unmatched values as-is...

    # or instead of the else: clause
    # just return something before the end of the function e.g.
    return hab  # leave unmatched values as-is...

You could also use a dict.get:

Expression:

lookup.get(!Hab_Class!, !Hab_Class!)

Code Block:

lookup = {
    'Lowest': '1. Lowest',
    'Marginal': '2. Marginal',
    'Moderately High': '3. Moderately High',
    'Highest': '4. Highest'
}
1
  • 1
    Nice. I like the dict.get with the default value. Very elegant.
    – Fezter
    Jan 22 at 1:18

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.