# List domain values for a field

3266
6
04-11-2019 07:59 AM
by
New Contributor II

I am quite stuck here: how do I list domain values for a field in a feature class?

To give you a broader context: after I got the domain values, I need to compare the values with the one from a shapefile and choose the correct one, strip the numbers from the text of the shapefile and populate the fields in my feature class.

I.e. shapefile value: "100 - apple" corresponds to domain value "abcd100 Apple"

So to begin with, I have so far failed to even list said domain values. Any code snippet would work and thanks for you help in advance

Tags (1)
6 Replies
MVP Regular Contributor

Hi Fugro ICT‌,

Domain values in a File Geodatabase (FGDB) are not stored at Feature Class level, but at FGDB level, i.e. a domain can be used in any Feature Class in the FGDB. This is done by assigning the domain to a certain field in a certain Feature Class.

That said, you can list your domain values like this (example taken from the docs: ListDomains—Help | ArcGIS Desktop - replace the Boston.gdb with yours):

import arcpydomains = arcpy.da.ListDomains("C:/Boston/Boston.gdb")for domain in domains:    print('Domain name: {0}'.format(domain.name))    if domain.domainType == 'CodedValue':        coded_values = domain.codedValues        for val, desc in coded_values.items():            print('{0} : {1}'.format(val, desc))    elif domain.domainType == 'Range':        print('Min: {0}'.format(domain.range[0]))        print('Max: {0}'.format(domain.range[1]))‍‍‍‍‍‍‍‍‍‍‍‍‍

Is this what you are looking for?

Egge-Jan

by
New Contributor II

Thanks! I have been staring at this little snippet today for far too long already  It gives me a nice list of all my domains for the gdb but how do I get only the one from my FC and from the specific field?

MVP Esteemed Contributor
 domain(Read and Write) The name of the associated domain.

Suggesting you will have to examine your featureclasses (ListFeatureClasses, their fields (ListFields) and check to see if the fields have that property

MVP Regular Contributor

When I wanted a count of domain values used in all fields in a feature, I used the following.  It ignores 'Range' type domains, but it might give you some ideas.  To limit it to a specific field, you could use something like:  field.name == 'field_name'.

import arcpygdb = r"C:\path\to\file.gdb"arcpy.env.workspace = gdb # set environment for arcpyfc = 'feature_name' # a feature in the geodatabase# gdb domains to dictionary # # # # # # #domDict = {} # empty dictionarydomains = arcpy.da.ListDomains(gdb)for domain in domains:    if domain.domainType == 'CodedValue':        if domain.name not in domDict:            vList = [] # empty list            coded_values = domain.codedValues            for val, desc in coded_values.items():                vList.append({val:desc})        domDict[domain.name] = vList# print domDict# read feature's fields and domains information # # # # # # #fields = arcpy.ListFields(fc)fldDict = {} # empty dictionaryfor field in fields:    if len(field.domain):        fldDict[field.name] = field.domain# print fldDict# count values in fields with domains # # # # # # #domCount = {}fldList = list(fldDict.keys())with arcpy.da.SearchCursor(fc, fldList) as rows:    for row in rows:        for i, f in enumerate(fldList):            # print i, fldList, row # index, field name, field value            if fldList not in domCount:                domCount[fldList] = {}            if row not in domCount[fldList]:                domCount[fldList][row] = 1            else:                domCount[fldList][row] += 1del rows # release any locks# print domCount# output the results # # # # # # #for k, v in domCount.iteritems():    print "Field: {}".format(k)    print "  Domain: {}".format(fldDict)    for dLst in domDict[fldDict]:        for k1, v1 in dLst.iteritems():            if k1 in v:                print "    Key:  {} - Description: {} - Count: {}".format(k1, v1, v[k1])            else:                print "    Key:  {} - Description: {} - Count: {}".format(k1, v1, 0)# note, this does not check for invalid codes in domain fields‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

An example of the output for one field:

Field: Observed  Domain: YN    Key:  Y - Description: Yes - Count: 159    Key:  ? - Description: ? - Count: 121    Key:  N - Description: No - Count: 255‍‍‍‍‍
by
New Contributor III

Hi Randy,

My apologies for the late reply. I actually got help by a consultant in the end, who worked on that script for a whole day

So this was the situation in our case:

# Classes and functions def get_domain_values(database, domain_name):    '''    Get domain values from the database    '''    domain_values = {}    msg = '...Get domain values from the database'    arcpy.AddMessage(msg)    in_workspace = database    out_table = os.path.join("IN_MEMORY", domain_name)    arcpy.DomainToTable_management(in_workspace=in_workspace,                                    domain_name=domain_name,                                    out_table=out_table,                                    code_field='CODE',                                    description_field='DESCRIPTION')    search_fields = ['CODE', 'DESCRIPTION']    with arcpy.da.SearchCursor(out_table, search_fields) as cursor:        for row in cursor:            domain_values[format(row[0])] = format(row[1])    return domain_values‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

And then the code:

# Get domain values for symbology code    domain_name = 'SYMBOL_LINE'    symbology_code_domain_list = get_domain_values(FGDB_path, domain_name)    # Read Name field and update symbology_code_field field    with arcpy.da.UpdateCursor(inmem_SWshape, [symbology_code_field, 'Name']) as cursor:        geometry_type = 'LINE '        for row in cursor:            try:                IDdesc = row[1].upper()                if IDdesc.startswith(geometry_type):                    IDdesc = IDdesc.replace(geometry_type, '')                domain_code = IDdesc.split(' ')[0]                if domain_code in symbology_code_domain_list:                    row[0] = domain_code                else:                    row[0] = default_iogp_code            except:                row[0] = default_iogp_code                arcpy.AddMessage("...ERROR: Checking Symbology Code failed")            cursor.updateRow(row)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

So he figured to export the domain as a table and then read the table in the script. Sounds like a good way to me!

I will surely need your script at a later point as well Randy, so your effort is highly appreciated!

New Contributor

def get_domain_values(feature, field):
feature_fields = [f for f in arcpy.ListFields(feature)]

if field.upper() not in [x.name.upper() for x in feature_fields]:
raise ValueError("Did not find field: {} in {}".format(field, feature))

gdb = arcpy.Describe(feature).path

target_field = [f for f in feature_fields if f.name.upper() == field.upper()][0]
target_field_domain = target_field.domain

if target_field_domain:
field_domain = [d for d in arcpy.da.ListDomains(gdb) if d.name == target_field_domain][0]
domain_values = field_domain.codedValues

return domain_values

return False