Is there a way to derive values using the Search Cursor and then update another field with those values?

1397
15
10-10-2019 08:57 AM
RPGIS
by
Occasional Contributor III

Hi,

So I have a slight predicament for this given scenario. I need to take the last 4 characters from the x coordinate and do the same for the y coordinate. I then need to combine the two and from the combined values, update another field. I have something akin but I keep running into errors. I can get it to list a set of values that I need but trying to get the update cursor to update the records in the field is tricky.

if field.name == 'FACILITY_ID':
            print field.name

            for row in arcpy.da.SearchCursor(fc, ["FACILITY_ID", "SHAPE@X", "SHAPE@Y"], """FACILITY_ID IS NULL"""):
                rowx = str(row[1])
                rowy = str(row[2])
                x = rowx[0:4]
                y = rowy[0:4]
                xy = x + y
            for row in arcpy.da.UpdateCursor(fc, ["FACILITY_ID"], """FACILITY_ID IS NULL"""):
                row.updateRow([xy])
                print '{} = {}'.format(field.name, xy)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Any help on this would be greatly appreciated.

0 Kudos
15 Replies
JoshuaBixby
MVP Esteemed Contributor

What is going on with Line #01, are you just missing an if statement?

Try the following:

if field.name == 'FACILITY_ID':
            print field.name
            
            with arcpy.da.UpdateCursor(fc, ["FACILITY_ID", "SHAPE@X", "SHAPE@Y"], """FACILITY_ID IS NULL""") as cur:
                for fid, x, y in cur:
                    xy = str(x)[:4] + str(y)[:4]
                    cur.updateRow([xy, x, y])‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
RPGIS
by
Occasional Contributor III

Thank you very much Joshua. I thought for some reason that if I wrote the script to Search Cursor then it could only be written to search cursor. I wasn't quite sure how to combine the search and update cursors into one, or if there was a way to run one then the other. The other concern that I had (this is probably due to my limited understanding of python) is I was afraid that if I set the update cursor with the SHAPE@X and SHAPE@Y that those records in those fields might get populated. If that isn't the case then I worried for nothing. 

I will give your script a try and let you know how it goes.

Also, I forgot to include the elif when I copied this script into my question. I will go back and change it so that way there is no confusion or anything.

0 Kudos
RandyBurton
MVP Alum

You don't need both a SearchCursor and an UpdateCursror. Just use the UpdateCursor:

with arcpy.da.UpdateCursor(fc,['FACILITY_ID', 'SHAPE@X', 'SHAPE@Y'],'''FACILITY_ID IS NULL''') as cursor:
    for row in cursor:
        x = str(abs(int(row[1])))[:4]
        y = str(abs(int(row[2])))[:4]
        row[0] = x + y # concatenate strings x and y
        cursor.updateRow(row)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

If you really want to use the x and y coordinates to create a facility ID, you may wish to format the x/y in such a way to consistently get your number.  These values will be a type float, with a decimal somewhere.  It may also be a negative number.  So both a minus sign and a decimal may appear in your concatenation string.  I converted these values to a positive integer before taking the right 4 digits.  It should also be noted that the facility ID may not be unique, and it is a string so the facility ID should be type text.

RPGIS
by
Occasional Contributor III

Thanks Randy.

I tried just using the update cursor but I wasn't sure if I used the update cursor with the shape@x or shape@y if it would work. I will also try your script as well.

Robert

0 Kudos
RPGIS
by
Occasional Contributor III

Hi Randy,

Your script worked and it also raised another question/concern that I have. I don't know if I should post another question or if it is fine posting it here.

When there are several fields listed for the update cursors, like what you and Joshua posted, is there a way to specify which particular field gets updated? I wasn't quite sure if there was, but part of the reason I wrote some of my scripts like what I posted, is because I wasn't sure if there was a way to do so. Your example worked and I wasn't sure if something akin to that would work. So is it possible list multiple fields and only have specific records in one of the fields get populated. Also, does this also work for a set of records in multiple fields?

Any clarity on this would help me better understand how to go about writing these kind of scripts better.

Thanks,

Robert

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

The cursor.updateRow() method requires the list passed to it match the number of fields in the cursor.  If you want to update one field out of three, just pass the original values back to the method for the 2 fields you don't want to change.

RandyBurton
MVP Alum

Each row in the update cursor contain a list of the field values returned.  In this case:

the field list:  ['FACILITY_ID', 'SHAPE@X', 'SHAPE@Y']

row[0] = FACILITY_ID
row[1] = SHAPE@X
row[2] = SHAPE@Y

So changing the value of row[0] would cause the facility ID to be updated.  I suppose in reality all the fields in the row are actually updated, it is just that unless the value has been changed, the update would not be noticeable.

Instead of using indexing (ie. row[0]), you can use Joshua Bixby's approach to read the cursor into specific named variables.  This might be an easier way to keep things organized.  See the last three lines in Joshua's code.  In line 4 of his code, change the SearchCursor to an UpdateCursor (I think this was just a typo).

Hope this helps.

JoshuaBixby
MVP Esteemed Contributor

Thanks for the catch Randy; yes, it was a typo.  I have updated the original code snippet I replied with.

UDPATE:  Argh, updated again.  Man, I was not paying attention writing code this morning.

0 Kudos
RPGIS
by
Occasional Contributor III

Thanks Randy for clarifying. I really wasn't quite sure if setting the update cursor with multiple fields listed as the cursor would result in all of those field records being updated, much less being able to specify which of the fields in the list need updating. I also didn't know that you could specify field names in a cursor as named variables like the one Joshua posted. I will try his script again, but I will also try it with another part of the script that I am working on.

I wish there was more information like what you and Joshua provided available. I tried researching to find the best approach with the scripts that I am working on, and I wasn't able to find much.

Thanks again Randy and Joshua for the much needed help. I haven't been scripting much and I found the opportunity to when I told my supervisor that it would be easier to automate populating certain fields rather than manually doing so. My scripting knowledge is still very limited so I tend to ask around and see if anyone else can provide a better solution for what I am trying to accomplish. 

If you, Joshua, or anyone else has any tips to that would help with improvements I would definitely be open to it.

0 Kudos