TransWikia.com

ArcPy - iteration to calculate the mean of specific fields to use it as input for further calculations in the same feature/table

Geographic Information Systems Asked by Monitotier on January 4, 2021

I am working with ArcPy under Python 2.7.

I have a bunch of shapefiles that have the same structure.
I want to iterate through all of them to add a field (A1_norm) and filling it with the multiplications of (A1) by its ( mean= 2). This will be repeated for (A2)
The expected result would be something like this:

A    A_norm 
1     0.5
2      1
3     1.5

To do so, I have developed several options of code:

First approach

#setting the workspace
env.workspace =  r'C:Users..'
# creating a list of features
listC = arcpy.ListFeatureClasses('*', 'all')
# adding the list of fields to a (list)
fieldlist = arcpy.ListFields('myShape.shp')
# Checking list all the fields of the feature/shape
for field in fieldlist:
    print(field.name, field.type)

For which I get:

(u'FID', u'OID')
(u'Shape', u'Geometry')
(u'Id', u'Integer')
(u'A1', u'Double') #target field
(u'A2', u'Double') # target field

I define my formula:

def calculate_mean_value(table, field):
    na = arcpy.da.TableToNumPyArray(table, field)
    return np.mean(na[field])

# loop for calculating the mean of all the fields of the features listed on the env
for a in listC:
    for field in fieldlist:
        print (a, field.name, calculate_mean_value(a,field.name))

This works, but if I want to adapt the code to get the mean of my target fields:

# storing the field names in a list
field_namesT = [f.name for f in arcpy.ListFields('myShape.shp')if f.name.startswith('A')]

#trying to calculate the mean for the 2 targeted fields: 
for a in listC:
    for field in field_namesT:
        print (a, field.name, calculate_mean_value(a,field.name))

The error:

AttributeError: 'unicode' object has no attribute 'name'

Second approach:

# setting the work space
env.workspace =  r'C:Users..'

expression= calculate_mean_value(field.name)

#First, create the fieldlist with a loop for. With this I'll create the table
# these are the new fields that are going to be added to the shapefile
fieldlist1 = ["A1_Norm","A2_Norm"]
for field in fieldlist1:
    arcpy.AddField_management('myShape.shp',field,"DOUBLE")

#And now calculate fields
arcpy.CalculateField_management('myShape.shp',"A1_Norm","!A1!/(sum(!A1!)/len(!A1!))!","PYTHON")
arcpy.CalculateField_management('myShape.shp',"A2_Norm","!A2!/(sum(!A2!)/len(!A2!))!","PYTHON")

The error:

ExecuteError: ERROR 000539: Error running expression: 0.690857157697 /np.mean(0.690857157697) 
Traceback (most recent call last):
  File "<expression>", line 1, in <module>
NameError: name 'np' is not defined

Failed to execute (CalculateField).

Third approach:

# setting the work space
env.workspace =  r'C:Users'
# Set local variables
shape = 'myShape.shp'
fieldT = 'A1'
expression = 'fieldT/calculate_mean_value(shape, fieldT)'
fieldR ='A1_Norm'


codeblock = """
def calculate_mean_value(shape, fieldT):
    na = arcpy.da.TableToNumPyArray(shape, fieldT)
    return np.mean(na[fieldT])"""
 
# Execute AddField
arcpy.AddField_management(shape, fieldR, "DOUBLE")
 
# Execute CalculateField 
arcpy.CalculateField_management(shape, fieldR, expression,"PYTHON", codeblock)

The error:

ExecuteError: ERROR 000539: Error running expression: fieldT/calculate_mean_value(shape, fieldT) 
Traceback (most recent call last):
  File "<expression>", line 1, in <module>
NameError: name 'fieldT' is not defined

Failed to execute (CalculateField).

Can anyone give me a hint of how to solve this issue?

One Answer

The following approach calculates the mean of A and writes the value of A * mean(A) in the A_norm field.

import arcpy

arcpy.env.workspace = '/path/to/your/workspace'
fcs = arcpy.ListFeatureClasses()

for fc in fcs:
    # Add "A_norm" field
    arcpy.AddField_management(fc, "A_norm", "DOUBLE")

    # Find mean of A
    vals = [row[0] for row in arcpy.da.SearchCursor(fc, "A")]
    mean = sum(vals)/len(vals)

    # Calc field
    with arcpy.da.UpdateCursor(fc, ("A", "A_norm")) as cursor:
        for row in cursor:
            row[1] = row[0] * mean
            cursor.updateRow(row)

Correct answer by Aaron on January 4, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP