I can do it with a basic arcpy.da.UpdateCurosr but I am trying to figure out how to use arcpy.da.UpdateCurosr with dictionary key. I am trying to populate Field1 if the row is blank but if not then continue on to the next row. I have the following but I get error,
upd_row[0] = search_feats[upd_row[1]] #FIELD_2
KeyError: 'Blah Text'
>>>
flds = ['Field1','Field']
search_feats = {f[0]:f[1:] for f in arcpy.da.SearchCursor(fc1, flds)}
with arcpy.da.UpdateCursor(fc1, flds) as upd_cur:
for upd_row in upd_cur:
#if upd_row[0] is None:
if upd_row[0] != None:
#if upd_row[0] in ("", ' ', None):
upd_row[0] = search_feats[upd_row[1]] #FIELD1
upd_cur.updateRow(upd_row)
del upd_cur
Solved! Go to Solution.
I created a quick feature for illustration. It contains the following:
To copy the value from Field2 to Field1 using a dictionary, I modified your code and added some explanation:
fc1 = 'DictionaryTest'
flds = ['OBJECTID','Field1','Field2']
# for clarity, put f[1:] in parenthsis - this will be a tuple
search_feats = {f[0]:(f[1:]) for f in arcpy.da.SearchCursor(fc1, flds)}
# Produces this dictionary: {1: (u'', u'AA2'), 2: (u'bb1', u'BB2'), 3: (None, u'CC2')}
# key = 1, value[0] = empty string, value[1] = 'AA2'
# key = 2, value[0] = bb1, value[1] = 'BB2'
# key = 3, value[0] = None/Null, value[1] = 'CC2'
with arcpy.da.UpdateCursor(fc1, flds) as upd_cur:
for upd_row in upd_cur:
# if upd_row[0] == None:
# this is the OBJECTID, it should always have a value
# is the OBJECTID in the search_feats dictionary?
if upd_row[0] in search_feats.keys():
# upd_row[1] is 'Field1' and upd_row[2] is 'Field2'
# search_feats[upd_row[0]] is the dictionary key, 'Field2' is the second value of the dictionary [1]
upd_row[1] = search_feats[upd_row[0]][1]
upd_cur.updateRow(upd_row)
# OBJECTID not in dictionary
else:
pass
The result is:
Field1 now contains the same values as Field2. For something this simple, I wouldn't use a dictionary. It would work best in place of joining two features on a common field to copy values from one feature to the other. It may also be helpful in some other cases.
Hope this helps.
What is the error you are getting?
Here is how I've done something similar in the past:
tableFields = ['SITEID','SITE_GUID']
source = r'some\path\to\data table'
guidDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(source,tableFields)}
with arcpy.da.UpdateCursor(updateTable,updateFields) as updateRows:
for updateRow in updateRows:
keyValue = updateRow[0]
if keyValue in guidDict and updateRow[1] == None:
updateRow[1] = guidDict[keyValue][0]
updateRows.updateRow(updateRow)
else:
pass
Joe, thanks for the response. I see but after using your code and implementing my data and running the code field1 is not being populated with field2 if the fied1 rows are blank.
The error I was getting was with my code was;
Traceback (most recent call last):
File "D:\GIS Folder Scripts\UpdateFiledBlanks.py", line 10, in <module>
upd_row[0] = search_feats[upd_row[1]] #FIELD_2
KeyError: 'Final Plat'
flds = ['Field1','Field']
search_feats = {f[0]:f[1:] for f in arcpy.da.SearchCursor(fc1, flds)}
In this bit of your code, 'Field1' id becoming the dictionary key f[0]. A dictionary key cannot be blank. Field1 should be unique, something like an object id ('OID@' for example)
That was my initial thought and makes sense but if Field1 is unique pass field2 and field3 to updatecursor and update field1 with field2 if filed1 is blank? I am still trying to make sense of Dictionary keys and how to loop through them.
put your latest iteration of your code up and I'll see if I can figure it out.
I think the better way to see if a value is None (<Null>) you should use
is None instead of == None
The thing you need to be sure is you are checking for it and doing something when it is null and something else when it isn't.
if x is not None:
pass
else:
do something
#### or
if x is None:
do something
else:
pass
See Can you explain in simple terms what 'is not None' in Python 3.x is? - Quora ; a guy named Troy Hoffman gives a good explanation in his comment.
This is what I've got, I posted the wrong one at first.
I get no errors but field1 row doesn't get populated with field2 is field1 row is blank.
flds = ['field1','field2']
search_feats = {f[0]:f[1] for f in arcpy.da.SearchCursor(fc1,flds)}
with arcpy.da.UpdateCursor(fc1,flds) as upd_cur:
for upd_row in upd_cur:
if upd_row[1] == None:
upd_row[1] = search_feats[upd_row[0]]
upd_cur.updateRow(upd_row)
else:
pass
del upd_cur
I created a quick feature for illustration. It contains the following:
To copy the value from Field2 to Field1 using a dictionary, I modified your code and added some explanation:
fc1 = 'DictionaryTest'
flds = ['OBJECTID','Field1','Field2']
# for clarity, put f[1:] in parenthsis - this will be a tuple
search_feats = {f[0]:(f[1:]) for f in arcpy.da.SearchCursor(fc1, flds)}
# Produces this dictionary: {1: (u'', u'AA2'), 2: (u'bb1', u'BB2'), 3: (None, u'CC2')}
# key = 1, value[0] = empty string, value[1] = 'AA2'
# key = 2, value[0] = bb1, value[1] = 'BB2'
# key = 3, value[0] = None/Null, value[1] = 'CC2'
with arcpy.da.UpdateCursor(fc1, flds) as upd_cur:
for upd_row in upd_cur:
# if upd_row[0] == None:
# this is the OBJECTID, it should always have a value
# is the OBJECTID in the search_feats dictionary?
if upd_row[0] in search_feats.keys():
# upd_row[1] is 'Field1' and upd_row[2] is 'Field2'
# search_feats[upd_row[0]] is the dictionary key, 'Field2' is the second value of the dictionary [1]
upd_row[1] = search_feats[upd_row[0]][1]
upd_cur.updateRow(upd_row)
# OBJECTID not in dictionary
else:
pass
The result is:
Field1 now contains the same values as Field2. For something this simple, I wouldn't use a dictionary. It would work best in place of joining two features on a common field to copy values from one feature to the other. It may also be helpful in some other cases.
Hope this helps.
Awesome, thanks for the explanation on this.
I get no errors but field1 row doesn't get populated with field2 if field1 row is blank.
There is huge difference between None and a Blank or Empty field. The None value, which is python's way of denoting the <Null> value is a specific value: NULL. A blank or empty field is not null; it has at least one space in it. Numeric and date fields can't have a space in them, so they are Null by default. However, a space in a text field (or fifty spaces) will torpedo your use of is None or == None every time. Check your data! I can't tell you how many calories I've burned converting blank fields to Null values. ( But I'm still pudgy...)
Dictionaries are relatively simple once you get used to using them. They are in the form of:
Key:Value
All the keys must be unique, and you can only have one value per key. Remember though, the value can be a tuple so that's a way to cheat the one key one value rule. (You can 'nest' dictionaries too, but that gets too weird for me.) Think about a any table in a database; it's basically a dictionary. It has an object id (key) and a tuple of values:
{1:('feild1','field2', 'field...n'),
2:('feild1','field2', 'field...n'),
3:('feild1','field2', 'field...n')}
etc
The trick with dictionaries and update cursors is being able to identify the unique key and extract the value associated with that unique key that you want.
Hope this helps.