Add Values to Table using UpdateCursor()

343
6
Jump to solution
11-01-2023 11:02 AM
AnjeliDubey
New Contributor II

Hi, I am fairly new to ArcPro and this is my first time using UpdateCursor() and I was wondering how I can have each row in a field to have a value from a list in the order it appears in the list? For example, if I have a list:

["1","5","3"]

How can I make it so 1 is the value for the first row in the field, 5 is the value for the second row, and 3 is the value for the third row? Thank you

0 Kudos
1 Solution

Accepted Solutions
BlakeTerhune
MVP Regular Contributor

A basic solution using updateCursor would be like this:

 

lookup_values = ["1","5","3"]

with arcpy.da.UpdateCursor(my_fc_path, ["FirstField", "Another_Field_ifyouwant"]) as update_cursor:
    for enum, row in enumerate(update_cursor):
        row[0] = lookup_values[enum]
        update_cursor.updateRow(row)

 

However, I would recommend not relying on the implicit order of everything like this. You're not guaranteed to go through the rows of data in any predictable order unless you specify a sql_clause parameter and use order by, but that's only supported when working with databases. This will also error if there are more rows in the cursor than you have lookup values in the list.

Rather, you should be matching by a key value. You would create a Python dictionary of your lookup values by some primary key id, then for each row in your update cursor, look up the key and get the value to change for that particular row.

Turbo Charging Data Manipulation with Python Curso... - Esri Community

Can you give some more context to your question so we can give you a more precise answer?

View solution in original post

6 Replies
BlakeTerhune
MVP Regular Contributor

A basic solution using updateCursor would be like this:

 

lookup_values = ["1","5","3"]

with arcpy.da.UpdateCursor(my_fc_path, ["FirstField", "Another_Field_ifyouwant"]) as update_cursor:
    for enum, row in enumerate(update_cursor):
        row[0] = lookup_values[enum]
        update_cursor.updateRow(row)

 

However, I would recommend not relying on the implicit order of everything like this. You're not guaranteed to go through the rows of data in any predictable order unless you specify a sql_clause parameter and use order by, but that's only supported when working with databases. This will also error if there are more rows in the cursor than you have lookup values in the list.

Rather, you should be matching by a key value. You would create a Python dictionary of your lookup values by some primary key id, then for each row in your update cursor, look up the key and get the value to change for that particular row.

Turbo Charging Data Manipulation with Python Curso... - Esri Community

Can you give some more context to your question so we can give you a more precise answer?

AnjeliDubey
New Contributor II

It is a bit complicated to explain what I am trying to do. I basically am running a calculation for each of these fields:

AnjeliDubey_0-1698865651909.png

And the calculations are then put into a dictionary:

{'OBS1': 18, 'OBS2': 18, 'OBS3': 17, 'OBS4': 16}

And I then need to put each value in another field "Field 1" in another table. So 18 needs to go in row 1, 18 needs to go in row 2, 17 needs to go in row 3, and 16 needs to go in row 4 if that makes sense.

AnjeliDubey_1-1698865876449.png

 

0 Kudos
BlakeTerhune
MVP Regular Contributor

Do either have these tables have a key id field that links a record from one table to the other?

0 Kudos
AnjeliDubey
New Contributor II

No, there are no key id fields that can link a record from one table to another. Should I add one with the AddField_management tool?

0 Kudos
BlakeTerhune
MVP Regular Contributor

This all seems rather arbitrary. How do you know which row in the destination table is for which calculation?

If you want to hard code the calculations like your original request, my original code sample should work (again, assuming you have the same number of rows in the destination table as you have calculated values).

If you want to read the calculated values from a table and insert them (instead of hard coding the values), you can do that too (again, add error handling in case you have more rows in the destination table than you have calculated values):

 

calcval_table_path = path_to_calcval_table_here
with arcpy.da.SearchCursor(calcval_table_path, ["OBS1", "OBS2", "OBS3", "OBS4"]) as search_cursor:
    for row in search_cursor:
        lookup_values = row

destination_table_path = path_to_destination_table_here
with arcpy.da.UpdateCursor(destination_table_path, ["Field1", "Another_Field_ifyouwant"]) as update_cursor:
    for enum, row in enumerate(update_cursor):
        row[0] = lookup_values[enum]
        update_cursor.updateRow(row)

The SearchCursor portion will make the lookup_values. It'll be whatever is the last row in that calculated values table.

 

0 Kudos
AllenDailey1
Occasional Contributor III

* Edit: I like BlakeTerhune's reply! That's better than my idea. *

That's great that you're trying out cursors!

When you say "each row in a field," by "row" do you mean feature/record, and by "field" do you mean an actual field/attribute?  I ask because usually with cursors, the word "row" can be a variable that might refer to attributes of one feature/record, in certain forms of syntax.  Just wanting to make sure I understand what you're getting at.  

Say you are wanting to assign those values in your list to three separate features/records in your table.  One way to achieve what you mentioned is to use a counter.  There might be a better way to do it; I'm experienced but not an expert.  Just keep in mind that the first item in your list is index number 0, of course.

Also keep in mind that which value gets applied to which record in your table depends on how the table is sorted when you run your code.  It does not necessarily run in order of ObjectID's.  I'm not sure what the scenario could be where you are doing what you're describing - maybe it would help if you explain that.

Here's an example of using a counter:

 

import arcpy
arcpy.env.workspace = r"path\to\geodatabase"
fc = "fc_name"
field = "fieldname"
valuelist = ["a", "b", "e", "z"]  # Values to be inserted
with arcpy.da.UpdateCursor(fc, field) as cursor:
    count = 0  # Starts at zero because list index starts with zero
    for row in cursor:  # For each record in the table:
        # This is supposed to prevent the following line from erroring 
        # out if count exceeds the length of the list
        while count < len(valuelist): 
            # Assign value from the valuelist to the record in the table
            row = valuelist[count]
            # Increment count to select next valuelist item next time
            count += 1
        cursor.updateRow(row)

 

0 Kudos