FieldCalculate Feature Class Attribute values by matching existing field values to dictionary

1004
6
Jump to solution
03-04-2019 10:19 PM
WilliamKalande
New Contributor III

I have a dictionary whose keys also appear are attribute values in a fc_1.

In the code below, I use the dictionary values to select by attribute rows (gid) in fc_1 with intention of writing the dictionary keys into another field in fc_1 using arcpy.SelectLayerByAttribute_management.

This only writes the last key in the dictionary against all the selected values.

import arcpy

arcpy.env.workspace = r'home\delete\cccgdb.gdb'
gc = 'fc_1'
field ='FIDF'
dictio={"a": "AAA", "b": "BBB", "c": "CCC", "d": "DDD"}
fc_1_lyr = arcpy.MakeFeatureLayer_management(gc, "fc_1_lyr")
for i in dictio.keys():
     for j in dictio.values():
         #print (j)
         whereClause = "gid = '%s'"%j
         print (whereClause)
         act = arcpy.SelectLayerByAttribute_management(fc_1_lyr, 'NEW_SELECTION', whereClause)
         expression ='%s'%i
         print(expression)
         arcpy.CalculateField_management(act, field, expression)
         arcpy.SelectLayerByAttribute_management(fc_1_lyr, "CLEAR_SELECTION")


print ('memaliza')‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

What am I doing wrong?

0 Kudos
1 Solution

Accepted Solutions
JoshuaBixby
MVP Esteemed Contributor

Try the following structure:

>>> dictio={"a": "AAA", "b": "BBB", "c": "CCC", "d": "DDD"}
>>> for k, v in dictio.items():
...     whereClause = "gid = '%s'"%v
...     print (whereClause)
...     expression ='%s'%k
...     print(expression)
...
gid = 'AAA'
a
gid = 'BBB'
b
gid = 'CCC'
c
gid = 'DDD'
d
>>>

View solution in original post

6 Replies
JoeBorgione
MVP Emeritus

For starters, format your text so it can be read: the lines in your nested for loop don't appear to be indented correctly (or are they?). 

That should just about do it....
0 Kudos
WilliamKalande
New Contributor III

Edited. Well indented in code. Didnt paste well in here

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Please read /blogs/dan_patterson/2016/08/14/script-formatting?sr=search&searchId=d5742ea6-9b0b-40f2-a083-9fbbc0d...‌, or watch the video /blogs/sergent/2015/02/18/formatting-your-code-in-geonet-for-the-visual-learner?sr=search&searchId=d...‌.

Formatting your original code snippet:

import arcpy
from arcpy import SearchCursor
arcpy.env.workspace = r'home\delete\cccgdb.gdb'
gc = 'fc_1'
field ='FIDF'
dictio={"a": "AAA", "b": "BBB", "c": "CCC", "d": "DDD"}
fc_1_lyr = arcpy.MakeFeatureLayer_management("fc_1", "fc_1_lyr")
for i in dictio.keys():
     for j in dictio[i]:
         #print (j)
         whereClause = "gid = '%s'"%j
         print (whereClause)
         act = arcpy.SelectLayerByAttribute_management(fc_1_lyr, 'NEW_SELECTION', whereClause)
         expression ='%s'%i
         print(expression)
         arcpy.CalculateField_management(act, field, expression)
         arcpy.SelectLayerByAttribute_management(fc_1_lyr, "CLEAR_SELECTION")


print ('memaliza')

Some questions/comments:

  1. You are importing SearchCursor but are not using it.  If you are using ArcPy cursors somewhere later in the code, I suggest using SearchCursor—Data Access module | ArcGIS Desktop instead of the legacy cursor.
  2. You define a gc variable but never use it.
  3. I am not sure if Line #9 is doing what you think, or maybe I don't understand what you are trying to do.  Since your dictionary is storing strings, dictio will return a string and for j will loop over each letter in the string.  Do you really want to create 3 identical WHERE clauses, e.g., gid = 'A', gid = 'A', gid = 'A' ?
WilliamKalande
New Contributor III

Edited code. I have dropped the legacy cursor and picked ArcPy cursors later in the code. Thanks

I use gc in a later section of the code which is running well. Have however edited to put it to immediate use in this section. 

Why I used dictio is because it didnt matter whether I picked A OR AAA. I however have modified to ensure it picks the entire dictionary value say AAA OR DDD. Still not successful. My output

gid = 'AAA'
a
gid = 'CCC'
a
gid = 'BBB'
a
gid = 'DDD'
a
gid = 'AAA'
c

whereeas my desired result is

gid = 'AAA'
a
gid = 'CCC'
c
gid = 'BBB'
b
gid = 'DDD'
d

and these values should be written in the attribute table. At the moment, its writing d in all the rows.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Try the following structure:

>>> dictio={"a": "AAA", "b": "BBB", "c": "CCC", "d": "DDD"}
>>> for k, v in dictio.items():
...     whereClause = "gid = '%s'"%v
...     print (whereClause)
...     expression ='%s'%k
...     print(expression)
...
gid = 'AAA'
a
gid = 'BBB'
b
gid = 'CCC'
c
gid = 'DDD'
d
>>>
wwnde
by
Occasional Contributor

Thanks. Edited as below. Working well.

import arcpy
arcpy.env.workspace = r'home\Desktop\delete\cccgdb.gdb'
gc = 'fc_1'
field =['FIDF', 'gid']
dictio={"a": "AAA", "b": "BBB", "c": "CCC", "d": "DDD"}
fc_1_lyr = arcpy.MakeFeatureLayer_management(gc, "fc_1_lyr")
for k, v in dictio.items():
        whereClause = '%s'%v
        expression ='%s'%k
        with arcpy.da.UpdateCursor(gc, field) as cursor: 
            for row in cursor: 
                if row[1] == whereClause:
                   row[0] = expression
                   cursor.updateRow(row) 
 
print ('memaliza')‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Cheers