Create a coded value attribute domain from unique values in a field

I often have to take data I have received containing redundant text fields, and turn it into something more meaningful. Often, this will involve extracting unique values from a text field and converting it into a coded value domain.

This has the advantage of minimising data capture errors resulting from spelling mistakes, and provides a nice dropdown list in whichever interface I choose to represent the layer in (whether it be ArcMap, ArcGIS Online, Collector or a web viewer).

This script has gone through various revisions since I first wrote it two years ago. Let’s take a closer look at line 22:

gen_cvd = sorted(set(row[0] for row in arcpy.da.SearchCursor(ftr, field_nam)), 
                 key=str.lower)

I’ve used a generator expression instead of a list comprehension to store all the values retrieved from the field using a search cursor. The amount of data I’m working with here didn’t really warrant the use of a generator – in fact, since I am performing multiple steps on this data (retrieving, dropping duplicates, sorting, looping), I probably should store it in a list.

However, I try to use different methods whenever I can so that I am always learning more about developing in my favourite language.

Using set, I remove duplicate values and then sort the values alphabetically. The cmp key str.lower is used to force case-insensitive sorting, otherwise uppercase values will be placed before lowercase values.

for dom_code, dom_value in enumerate(gen_cvd):
    arcpy.management.AddCodedValueToDomain(in_workspace=gdb,
                                           domain_name=cvd,
                                           code=dom_code,
                                           code_description=dom_value)

From Line 22, I use enumerate to add each value as a coded value to the attribute domain. Previously, I achieved this by doing the following:

vals = list(set([row[0] for row in arcpy.da.SearchCursor(ftr, field_nam)]))
codes = [c for c in xrange(0, len(vals)]
domDict = dict(zip(codes, vals))
for pair in domDict:
    ...

By using enumerate, I have a counter which can be used as the code part of the coded value pair.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s