0

I would like to search a specific field within an attribute table in ArcGIS Pro using ArcPy and find all the null values and change the null value to the value above it. For example:

ID | field1 | field 2
0     23       40
1     30       <Null>
2     20       18

In the example above, I would like to convert the Null value to 40. Here is my attempt below:

with arcpy.da.UpdateCursor(ScaleRatioTable,['Area_sqmi_1'])as cursor:
            for row in cursor:
                if row[1]=='<Null>':
                    row[1]=row[0]
                    cursor.updateRow(row)

I received the error that the "list index is out of range". I was wondering how I fix this code to make it run properly? I also don't understand the row[#]. Shouldn't the # be a variable? e.g.

n=0
n= n+1
if row[n] == None:
    row[n] = row [n-1]
3
  • 2
    Your example line of fields and values is a bit confusing, including me not seeing any NULL records. Regarding ArcPy cursors, SQL NULL is converted to Python None. What you are currently checking for is a string with the word '<NULL>', which isn't NULL.
    – bixb0012
    Commented Dec 30, 2022 at 21:16
  • 1
    ArcPy DA cursors are Pythonic -- NULL is None. This likely a duplicate with at least one Question.
    – Vince
    Commented Dec 30, 2022 at 21:25
  • 2
    Note that the actual cause of the error is not the the issue presented in the title, but the fact that you didn't list both the source and destination columns in the fields list.
    – Vince
    Commented Dec 30, 2022 at 23:10

1 Answer 1

2

You need to check if the field value is None not == '<Null>' or == None.

Your 1st attempt also fails as the row[n] are the indexes of the fields in each row, not a link to the previous row. So if you create a cursor with arcpy.da.UpdateCursor(ScaleRatioTable,['field1', 'field 2']), in every iteration of the for row in cursor: loop, row[0] is the value of 'field1' and row[1] is the value of 'field2'. And since you only asked for a single field, attempting to access row[1] raises an IndexError as row only has one element row[0].

It seems like you want to replace Null values with the value of the previous row in the same field. You would have to track the last non Null value yourself, e.g

last_non_null = None
with arcpy.da.UpdateCursor(ScaleRatioTable,['field1']) as cursor:
    for row in cursor:
        if row[0] is None:
            row[0] = last_non_null
            cursor.updateRow(row)
        else:
            last_non_null = row[0]

Note: You have to define last_non_null before the loop and because there aren't any non null values yet, I initialised it as None.

The only time this will be an issue is if the first row/s is None . You can however initialise the last_non_null variable as whatever you want. If you want a default value of 0 for the first N rows that don't have a value preceeding them, go for it.

e.g. Given:

ID | field N
0    <Null>
1    <Null>
2    40
3    <Null>
4    18
5    <Null>
6    <Null>

Output if last_non_null is initialised as None:

ID | field N
0    <Null>
1    <Null>
2    40
3    40
4    18
5    18
6    18

Output if last_non_null is initialised as 0:

ID | field N
0    0
1    0
2    40
3    40
4    18
5    18
6    18
2
  • Just to clarify, I want to loop through one field and replace all the rows with null values (None) with the value of the row above it, which is not a null value. In your example, if the row value is None, then it will equal the last non-null value, which makes sense, but why does the last non-null value = None? It should have a value to replace the null value. Thanks for your help! Commented Jan 3, 2023 at 17:25
  • @GIS_developer does this now answer your question?
    – user2856
    Commented Jan 7, 2023 at 6:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.