Select to view content in your preferred language

Dictionary upatecursor with domains

888
9
03-07-2023 11:46 AM
2Quiker
Occasional Contributor II

I am using the following but I get no error but it doesn't update the "State" field.

I've tested this on a different field and it works. The only thing about the "State" field is that it has a domain.

Is there something different I have to do in order for this to update the "State" field?

Also, this is in Pro.

 

 

 

import arcpy, os,sys

## Works in file geodatabase
arcpy.env.overwriteOutput = True
arcpy.env.workspace = r'C:\Temp\Sates.gdb'  


StSele = "States"
StStates = 'Statefile' 

sjpoints = "In_memory\sjpoints"

arcpy.SpatialJoin_analysis(StSele, StStates, sjpoints)
search_feats ={f[0] for f in arcpy.da.SearchCursor(sjpoints,"State_1")}
print(search_feats) 

place_dict = {"AL": "Alabama", "Ala": "Alaska", "OR": "Oregen", "Cal": "California", "WA": "Wasington"}
#print(place_dict)

with arcpy.da.UpdateCursor(StSele, "State") as upd_cur:
    for upd_row in upd_cur:
        upd_row[0] = place_dict.get(upd_row[0], upd_row[0])
        upd_cur.updateRow(upd_row)

 

 

9 Replies
DavidPike
MVP Frequent Contributor

Have you added those new values as domain values?

Your existing domains would be pointless anyway after the update cursor wouldn't they? Delete the domain then batch add Table to Domain after the cursor operation I would say.  (fyi spelling on Oregon)

0 Kudos
2Quiker
Occasional Contributor II

Have you added those new values as domain values?

Those domains were already there and I didn't not add them as new. I can't delete the domain as i am an editor on this feature class. Part of this snippet of code is ran when one of a few features are selected. If I were to click on that field attribute, I get a list to select from. So is the issue that there is domains?

0 Kudos
DonMorrison1
Occasional Contributor III

I was under the impression that Domains are not relevant to doing an update, but I could be wrong. I would add a print statements  in your loop to verify your inputs to updateRow

with arcpy.da.UpdateCursor(StSele, "State") as upd_cur:
    for upd_row in upd_cur:
        print (str(upd_row))
        upd_row[0] = place_dict.get(upd_row[0], upd_row[0])
        print (str(upd_row))
        upd_cur.updateRow(upd_row)

 

0 Kudos
2Quiker
Occasional Contributor II

I did add print statements but 'None' is being printed.

 

 

 

search_feats ={f[0] for f in arcpy.da.SearchCursor(sjpoints,"State_1")}
print(search_feats) 

place_dict = {"AL": "Alabama", "Ala": "Alaska", "OR": "Oregen", "Cal": "California", "WA": "Wasington"}
print(place_dict)

with arcpy.da.UpdateCursor(StSele, "State") as upd_cur:
    for upd_row in upd_cur:
        print(str(upd_row[0]))
        upd_row[0] = place_dict.get(upd_row[0], upd_row[0])
        print (str(upd_row[0]))
        upd_cur.updateRow(upd_row)

 

 

 

 

Print out

set([u'OR'])
{'OR': 'Oregen'}
None
None

 

 

0 Kudos
by Anonymous User
Not applicable

If some of your fields have Nulls, then the statement

upd_row[0] = place_dict.get(upd_row[0], upd_row[0])

is setting the upd_row[0] to None, because the second parameter in .get() is None.  Since nothing is returned when the .get() tries to find None in the dictionary, it defaults to the second argument.  If you replaced the statement with

upd_row[0] = place_dict.get(upd_row[0], 'No Key Found')

 

You'd get in your print out above:

set([u'OR'])
{'OR': 'Oregen'}  <- check you spelling, as @DavidPike mentioned
None
'No Key Found'

You need to get the domain values of the field and use those in your update to remain within the domain rules- look at the end of this thread for method of how you can get them:

list-domain-values-for-a-field 

0 Kudos
2Quiker
Occasional Contributor II

I guess I am confused. I thought that .get would get the place_dict value, e.g,  Alabama, Alaska etc.

There is empty/ blanks in the StSel layers "State"  field,which is why I am trying to update, and  which is why I lift out ' if row[0] in place_dict.keys()'

I was able to do what I needed by the following, but I would like to know how to dictionary keys and and dictionary values e.g. [0]

 

 

import arcpy, os,sys

## Works in file geodatabase
arcpy.env.overwriteOutput = True
arcpy.env.workspace = r'C:\Temp\Sates.gdb'  


StSele = "States"
StStates = 'Statefile' 

sjpoints = "In_memory\sjpoints"

arcpy.SpatialJoin_analysis(StSele, StStates, sjpoints)
search_feats ={f[0] for f in arcpy.da.SearchCursor(sjpoints,"State_1")}
print(search_feats) 

place_dict = {"AL": "Alabama", "Ala": "Alaska", "OR": "Oregon", "Cal": "California", "WA": "Wasington"}
#print(place_dict)

with arcpy.da.UpdateCursor(StSele, "State") as upd_cur:
    for upd_row in upd_cur:
        for key, value in search_feats.items():
            val = place_dict.get(value)
            upd_row[0] = val
            upd_cur.updateRow(upd_row)

 

 

0 Kudos
2Quiker
Occasional Contributor II

Is my issue, value of None that was causing the issue in line 8?

The StSele layer "States" filed does have "blanks" or/and "Nulls", that is correct as I am trying to update the StSele layers "State" field.

0 Kudos
by Anonymous User
Not applicable

You've got some mismatched variables to your last comment.  But, look at this and run it.

Some explanation of .get(): ref dictionary.get() 

exampleList = ["AL", "CO", "Cal", '', None, "WA", 'AZ']

place_dict = {"AL": "Alabama", "Ala": "Alaska", "OR": "Oregon", "Cal": "California", "WA": "Wasington"}

print('\nExplicitly setting the optional 2nd argument in .get():')
for val in exampleList:
    dVal = place_dict.get(val, 'explicitly set default')
    print(f'\tval: {val}\t\t.get(val, "explicitly set default") returned: {place_dict.get(val)}\t\tplace_dict returned: {dVal}')

print('\nNot setting the optional 2nd argument in .get(), which inherently defaults to None:')
for val in exampleList:
    dVal = place_dict.get(val)
    print(f'\tval: {val}\t\t.get(val) returned: {place_dict.get(val)}\t\tplace_dict returned: {dVal}')

print('\nSetting 2nd argument to val as default:')
for val in exampleList:
    dVal = place_dict.get(val, val)
    print(f'\tval: {val}\t\t.get(val, val) returned: {place_dict.get(val)}\t\tplace_dict returned: {dVal}')

 So this code shows that if the key is not in the dictionary, it will either return the string 'explicitly set default', None, or the val.

0 Kudos
2Quiker
Occasional Contributor II

Sorry for the delayed response, I got caught up on on something else.

I ran you code and I see, or at least I think I do. Maybe I didn't explain well what I am trying to do.

Maybe I am not going about it the correct way?

The  "States" field of the StSele layer will always most likely be blank. I need the States field updated, like so.

if StSele "State" field is empty/blank, check sjpoints (spatialjoin)--> if sjpints field "State_1" has "Ala" I need StSele layer field "States" updated with "Alaska. Again StSele "State" field will most likely be empty or blank.

My first table example was wrong, my apologies.

attributes after spatial join.

StStates Layer StSele layer Spaital Join
     
State State State_1
OR   Org
Ala   Ala
Cal   Cal
Wa   Wa

 

What I need the

StStates Layer StSele layer Spaital Join
     
State State State_1
OR Oregon Org
Ala Alaska Ala
Cal California Cal
Wa Washington Wa

 

0 Kudos