Select to view content in your preferred language

Calculate a "Race Code" or "Ethnicity Code" field from a "Race" field that is string format

271
10
Jump to solution
Tuesday
eallan
by
Occasional Contributor

I am trying to convert Race or Ethnicity values into a numeric code for them. For example, "White" would equal "0" , and "American Indian" would equal "1" , and "Latino" would equal "2", and so on and so forth.

I attached a screenshot and inbedded a photo below, that shows my attempt to do this, but I failed miserably. I've been looking online for over 1.5 hours now trying to find an answer or similar example I could go off of but have had no luck.

Screenshot 2025-05-20 172823.jpg

0 Kudos
1 Solution

Accepted Solutions
MErikReedAugusta
MVP Regular Contributor

Looks like you've got some basic syntax problems in your code.

To start with, python is indentation-based, and if/elif/else groups should all share the same indentation level.  The actions inside those if/elif/else conditions are one indentation level down from there.  Also, you do your condition, then your action, like so:

if condition:
    # do stuff
elif other_condition:
    # do other stuff
else:
    # do default stuff

 

Second, the field-names-with-exclamation-points thing isn't actually valid python.  It's a weird choice ESRI made with the outer layer of the interpreter and is only valid in the function call.  It will always throw an error if you put it in the code block.  This is one of my many gripes with the implementation of Field Calculator.

MErikReedAugusta_0-1747789792023.png

 

Lastly, this could be done quite a bit more simply with a list or dictionary lookup.

Try this code in the function call line:

GetRaceCode(!USER_Race!)

 

And then this code in the Code Block:

def GetRaceCode(string_value):
    # I took the order you used, but it honestly looks scrambled.  Make sure
    # to change any numbers that are wrong.  If they're all correct and in
    # order, and the duplicates are separate, then this technically could've
    # been done with a list.  But I'm going with a dictionary for simplicity
    # of editing, for you.
    options = {'White':                                     0,
               'American Indian':                           1,
               'Latino':                                    2,
               'No Response':                               3,
               '____ does not know':                        4,
               '____ asked, but has not provided':          5,
               'Black or African American':                 6,
               'Other':                                     7,
               'Black':                                     8,
               'Asian':                                     9,
               'Hawaiian':                                  10,
               'Native Hawaiian or Other Pacific Islander': 11,
              }

    # First, check to see if it's a valid, and accepted entry.
    # If so, pull it from the list above, and grab the value we said it was.
    # Dictionary calls in Python are formatted as dictionary_name[lookup_key]
    if string_value in options:
        return options[string_value]
    else:
        # NOTE: Zero is also your code for White.  Are you sure you want the
        # failsafe option to match one of the selections?  If not, change
        # this number to something not in the dictionary above.
        return 0 

 

------------------------------
M Reed
"The pessimist may be right oftener than the optimist, but the optimist has more fun, and neither can stop the march of events anyhow." — Lazarus Long, in Time Enough for Love, by Robert A. Heinlein

View solution in original post

10 Replies
MErikReedAugusta
MVP Regular Contributor

Looks like you've got some basic syntax problems in your code.

To start with, python is indentation-based, and if/elif/else groups should all share the same indentation level.  The actions inside those if/elif/else conditions are one indentation level down from there.  Also, you do your condition, then your action, like so:

if condition:
    # do stuff
elif other_condition:
    # do other stuff
else:
    # do default stuff

 

Second, the field-names-with-exclamation-points thing isn't actually valid python.  It's a weird choice ESRI made with the outer layer of the interpreter and is only valid in the function call.  It will always throw an error if you put it in the code block.  This is one of my many gripes with the implementation of Field Calculator.

MErikReedAugusta_0-1747789792023.png

 

Lastly, this could be done quite a bit more simply with a list or dictionary lookup.

Try this code in the function call line:

GetRaceCode(!USER_Race!)

 

And then this code in the Code Block:

def GetRaceCode(string_value):
    # I took the order you used, but it honestly looks scrambled.  Make sure
    # to change any numbers that are wrong.  If they're all correct and in
    # order, and the duplicates are separate, then this technically could've
    # been done with a list.  But I'm going with a dictionary for simplicity
    # of editing, for you.
    options = {'White':                                     0,
               'American Indian':                           1,
               'Latino':                                    2,
               'No Response':                               3,
               '____ does not know':                        4,
               '____ asked, but has not provided':          5,
               'Black or African American':                 6,
               'Other':                                     7,
               'Black':                                     8,
               'Asian':                                     9,
               'Hawaiian':                                  10,
               'Native Hawaiian or Other Pacific Islander': 11,
              }

    # First, check to see if it's a valid, and accepted entry.
    # If so, pull it from the list above, and grab the value we said it was.
    # Dictionary calls in Python are formatted as dictionary_name[lookup_key]
    if string_value in options:
        return options[string_value]
    else:
        # NOTE: Zero is also your code for White.  Are you sure you want the
        # failsafe option to match one of the selections?  If not, change
        # this number to something not in the dictionary above.
        return 0 

 

------------------------------
M Reed
"The pessimist may be right oftener than the optimist, but the optimist has more fun, and neither can stop the march of events anyhow." — Lazarus Long, in Time Enough for Love, by Robert A. Heinlein
Luke_Pinner
MVP Regular Contributor

Instead of:

    if string_value in options:
        return options[string_value]
    else:
        return 0 

You can use:

options.get(string_value, 0)  #  or replace 0 with preferred default value
MErikReedAugusta
MVP Regular Contributor

Clever!  Somehow I've never encountered/used this approach, and I love it.  Definitely saving for the future.

------------------------------
M Reed
"The pessimist may be right oftener than the optimist, but the optimist has more fun, and neither can stop the march of events anyhow." — Lazarus Long, in Time Enough for Love, by Robert A. Heinlein
RyanUthoff
MVP Regular Contributor

My screenshot below should work correctly. If you're writing your number values to a string field, then make sure to put quotes around the numbers.

I don't know how to properly explain it, but your Code Block cannot "see" your fields. You can't directly reference them using !Field_Name! syntax. Instead, you have to pass those fields to it from the line above. And then you reference your fields that way. Hopefully my screenshot will help explain it.

From there, you just have your if statements to calculate your values. And then at the very end, you need to return the value of "Race_Code" so it can calculate value in your table.

RyanUthoff_1-1747791731422.png

 

Edit: @MErikReedAugusta replied as I was typing my response and didn't see it until after I posted. Their method is more elegant and better than mine lol.

eallan
by
Occasional Contributor

Thank you Ryan for the help. Screenshots are the best!! Even though I didn't select yours as the solution, your suggestion is still an MVP!! ha . Have a good day!

0 Kudos
HaydenWelch
MVP Regular Contributor

If you don't actually care about the specific codes assigned to the values in that column, and just want to map specific string values to an integer, you can use a generic solution like this:

CODES: list[str] = []

def GetCode(value: str) -> int:
    # Pass Null (You can replace None with a default value like -1)
    if not value:
        return None
    
    if value not in CODES:
        CODES.append(value)
    return CODES.index(value)

 

This just creates a running list of all the string values it finds and uses the list index of the string as the return value.

 

This way you don't need to create a mapping of all possible values and can just let Python do it for you.

eallan
by
Occasional Contributor

Thank you Hayden for sharing that, I put it in my notes and bookmarked it. MUCH APPRECIATED!!!

BobBooth1
Esri Regular Contributor

There is a tutorial that includes a simple example of how to conditionally calculate values in one field based on values in another:

https://learn.arcgis.com/en/projects/identify-schools-for-a-mentoring-program/#subsection-18:~:text=...

 

eallan
by
Occasional Contributor

Thank you for that link Bob, I saved it in my notes and bookmarked it.

0 Kudos