I'm trying to read the [OWN] field and apply a domain value to 3 different fields with UpdateCursor, yet I keep getting a KeyError:
KeyError Traceback (most recent call last)
In [84]:
Line 49: row[0] = lookup_values['Fee']
KeyError: 'Fee'
The domains are already set and show up correctly on the a POLYGONS_feature_class. I'm sick of staring at this bit of code! Any ideas?
# defines OpCo, RightsType, and Type_of_Use fields
# by info in OWN field
gdb = projectfilepath + projectfileGDB
fc = POLYGONS_feature_class
domains = arcpy.da.ListDomains(gdb)
# 'OpCo' field
cur = arcpy.UpdateCursor(fc)
for row in cur:
if row.getValue('OWN') == 'INT %' or 'IT %' or 'TRANSMISSION, TAX DEPARTMENT':
fieldname = 'OpCo'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set 'OpCo' field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['IT']
cursor.updateRow(row)
# 'RightsType' field
cur = arcpy.UpdateCursor(fc)
for row in cur:
if row.getValue('OWN') == 'INT %' or 'IT %' or 'TRANSMISSION, TAX DEPARTMENT':
fieldname = 'RightsType'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set 'RightsType' field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['Fee']
cursor.updateRow(row)
# 'Type_of_Use' field
cur = arcpy.UpdateCursor(fc)
for row in cur:
if row.getValue('OWN') == 'INT %' or 'IT %' or 'TRANSMISSION, TAX DEPARTMENT':
fieldname = 'Type_of_Use'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set Type_of_Use field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['Full T-Line']
cursor.updateRow(row)
Solved! Go to Solution.
That error means there's no key of "Fee" lookup_values dictionary when you build it for the RightsType field. Some things to check:
Like this then?
fields = ["OWN1", "OpCo", "RightsType", "Type_of_Use"]
with arcpy.da.UpdateCursor(fc, fields) as u_cursor:
for own1, opco, rightstype, type_of_use in u_cursor:
if own1 in ("ITC", "TRANSMISSION, TAX DEPARTMENT"):
opco = "ITCT"
elif own1 == "CONSUMERS":
opco = "METC"
u_cursor.updateRow([own1, opco, rightstype, type_of_use])
That error means there's no key of "Fee" lookup_values dictionary when you build it for the RightsType field. Some things to check:
Thanks Blake!
1. Yep, a domain is assigned to the RightsType field
2. Yes, the domain has "Fee"
3. GREAT IDEA!!! I had stored the wrong codes in my domain dictionary.
I had feeling it was something really obvious (it always is, isn't it?
@BlakeTerhune, would you happen to know why when I repeat the code within the same feature class looking for a different domain value within the same domain, the cursor merely writes over the entire field with the new domain?
cur = arcpy.UpdateCursor(fc)
for row in cur:
if row.getValue('OWN') == 'CONSUMERS':
fieldname = 'OpCo'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set 'RightsType' field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['MET']
cursor.updateRow(row)
I'm either misunderstanding your question or your original intent. Your code is applying the same value to that field on every row. If you want it to apply a lookup value based on what's already in the field, then you probably want to change it like this.
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values[row[0]]
cursor.updateRow(row)
My apologies if I'm not answering the correct question.
@BlakeTerhune, no need to apologize, I appreciate your help! For context, I posted the feature class' attribute table that the code produces below the python.
cur = arcpy.UpdateCursor(fc)
for row in cur:
if row.getValue('OWN1') == 'ITC' or 'TRANSMISSION':
fieldname = 'OpCo'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set 'OpCo' field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['ITCT']
cursor.updateRow(row)
if row.getValue('OWN1') == 'CONSUMERS':
fieldname = 'OpCo'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set 'OpCo' field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['METC']
cursor.updateRow(row)
@nsidaniel wrote:@BlakeTerhune, no need to apologize, I appreciate your help! For context, I posted the feature class' attribute table that the code produces below the python.
So I assume your question is not answered? Could you describe exactly what you want to do?
So, I run the code from my initial question that (thanks to your suggestion) is running wonderfully, here's a sample:
cur = arcpy.UpdateCursor(fc)
for row in cur:
if row.getValue('OWN1') == 'ITC' or 'TRANSMISSION':
fieldname = 'OpCo'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set 'OpCo' field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['ITCT']
cursor.updateRow(row)
But, then I run the next portion:
cur = arcpy.UpdateCursor(fc)
for row in cur:
if row.getValue('OWN1') == 'CONSUMERS':
fieldname = 'OpCo'
field = arcpy.ListFields(fc, fieldname)[0]
for domain in domains:
if domain.name == field.domain:
coded_values = domain.codedValues
lookup_values = dict(zip(coded_values.values(),coded_values.keys()))
break
# Set 'OpCo' field
with arcpy.da.UpdateCursor(fc, fieldname) as cursor:
for row in cursor:
row[0] = lookup_values['METC']
cursor.updateRow(row)
It spits out:
the OpCo field should all contain "METC"
In theory, if OWN1 contains CONSUMERS, OpCo should be"METC"
and if OWN1 contains ITC or TRANSMISSION, OpCo should be"ITCT"
You're still not telling me what you are tying to do. I'm still guessing, but here's another method to consider.
# Build dictionary of domain objects for each field.
domains = arcpy.da.ListDomains(gdb)
field_domain = {}
for field in arcpy.ListFields(fc):
dom = [d for d in domains if d.name == field.domain]
if dom:
field_domain[field.name] = dom[0]
# Update data to change code to description.
fields = ["OWN1", "OpCo", "RightsType", "Type_of_Use"]
with arcpy.da.UpdateCursor(fc, fields) as u_cursor:
for own1, opco, rightstype, type_of_use in u_cursor:
# Pick the right domain coded values
if own1 in ("ITC", "TRANSMISSION"):
coded_values = field_domain["OpCo"].codedValues
elif "INT " in own1 or "IT " in own1 or own1 == "TRANSMISSION, TAX DEPARTMENT":
coded_values = field_domain["RightsType"].codedValues
# elif a_field == some other condition:
# coded_values = field_domain["a_field"].codedValues
else:
raise Exception(f"This data doesn't match any criteria.\n{[own1, opco, rightstype, type_of_use]}")
# Change field value.
own1 = coded_values['ITCT']
# Update the row.
u_cursor.updateRow([own1, opco, rightstype, type_of_use])
I apologize for my terrible explanations, @BlakeTerhune!
My initial question was how to read one field and then apply a domain value to another field with UpdateCursor. (To be honest I had written successful code for this ... then accidentally changed something.) You helped immensely, which I very much appreciate!
After I applied your suggestion, I then attempted to update the code to search the OWN1 field for "ITC", and "TRANSMISSION, TAX DEPARTMENT", or "CONSUMERS.
It was supposed to search the OWN1 field:
If it found "ITC", or "TRANSMISSION, TAX DEPARTMENT", it would change the OpCo field to "ITCT".
If it found "CONSUMERS", it would change the OpCo field to "METC".
Instead, the code wrote only "ITCT" or "METC" in the OpCo field depending on which I ran first. I'm sure it's obvious that I'm new to coding (but unfortunately, I kind of love it), and cannot see what's wrong.
Hopefully, that makes sense! No matter what, thank you for your time.