Setting expression and code block as a script tool parameter when calculating field

1907
14
Jump to solution
10-04-2023 09:45 PM
JasmineSpring
Occasional Contributor

Hello

I am having trouble is my script tool to set the parameters for the expressions and the code block. Is this something that is possible? If it is, to check Im adding the paramters correctly what do I need to specify? (ie data type, direction)  Thank you so much for your help!

import arcpy
POAlayer = arcpy.GetParameterAsText(0)
POAexpression = arcpy.GetParameterAsText(1)
POAcode = arcpy.GetParameterAsText(2)

# Calculate field

arcpy.management.CalculateField(POAlayer, "POA", POAexpression, "PYTHON3", POAcode)

 

0 Kudos
2 Solutions

Accepted Solutions
BlakeTerhune
MVP Regular Contributor

@JasmineSpring wrote:

Thank you so much !  I am trying to test the calculation with the null values already = 1 as below. I get the error NameError: name 'poa_fields_expr ' is not defined


The variable on line 11 needs to be renamed.

 

import arcpy

# Get the selected layer
layer = arcpy.GetParameterAsText(0)

# Create a list of field names starting with "poa"
poa_fields = [field.name for field in arcpy.ListFields(layer) if field.name.startswith("poa")]


 # Use the Field Calculator to calculate the product
poa_fields_expr =  " * ".join([f"!{field}!" for field in poa_fields])
expr = f"my_calc_func({poa_fields_expr})"

# *args allows any number of arguments to be passed into the function.
code = '''def my_calc_func(*args):
    result = 1
    for poa_value in args:
        result = result * poa_value
    return 1 - result
'''
arcpy.management.CalculateField(layer,"Product_poa",expr,"PYTHON3",code)

 

View solution in original post

JasmineSpring
Occasional Contributor

Thank you Blake ! Very much appreciated. That works perfectly. Below is the final solution

import arcpy

# Get the selected layer
layer = arcpy.GetParameterAsText(0)

# Create a list of field names starting with "poa"
poa_fields = [field.name for field in arcpy.ListFields(layer) if field.name.startswith("poa")]

for field in poa_fields:
    with arcpy.da.UpdateCursor(layer, poa_fields) as cursor:
        for row in cursor:
         row = tuple([1 if v is None else v for v in row])
         cursor.updateRow(row) 
   

 # Use the Field Calculator to calculate the product
poa_fields_expr =  " * ".join([f"!{field}!" for field in poa_fields])
expr = f"my_calc_func({poa_fields_expr})"

# *args allows any number of arguments to be passed into the function.
code = '''def my_calc_func(*args):
    result = 1
    for poa_value in args:
        result = result * poa_value
    return 1 - result
'''
arcpy.management.CalculateField(
    in_table=layer,
    field="Product_poa",
    expression=expr,
    expression_type="PYTHON3",
    code_block=code
)

 

View solution in original post

14 Replies
BlakeTerhune
MVP Regular Contributor

I don't see why it wouldn't work. Seems easy enough to test as-is though. Can you clarify what you're having trouble with?

0 Kudos
JasmineSpring
Occasional Contributor

Thanks for your help. Im having troubles to try to define the parameters in the tool to make it work right.

JasmineSpring_0-1696559740179.png

I couldnt find the data type option that made it work.

thank you !

0 Kudos
BlakeTerhune
MVP Regular Contributor

Does it work if you define POAexpression and POAcode as String?

0 Kudos
AlfredBaldenweck
MVP Regular Contributor

To your original post, I'd suggest 

 

POAlayer = arcpy.GetParameter(0)

 

 to return a layer object instead of a string, and see if that fixes it.

0 Kudos
JasmineSpring
Occasional Contributor

I used the parameter for the input layer as a layer. Thank you !

0 Kudos
JasmineSpring
Occasional Contributor

Hi ,

I am trying another way to do this using  update cursor and field calculator unsuccessfully.  I am wanting to change the null values of selected fields in feature class and multiply these fields and subtract them from 1 with the results in a new field. Thank you for you help

 

import arcpy

# Get the selected layer
layer = arcpy.GetParameterAsText(0)

# Create a list of field names starting with "poa"
poa_fields = [field.name for field in arcpy.ListFields(layer) if field.name.startswith("poa")]

for field in poa_fields:
  with arcpy.da.UpdateCursor(layer, poa_fields) as cursor:
    for row in cursor:
      if row[0] is None:
         row[0]="1"
         cursor.updateRow(row)

# Use the Field Calculator to calculate the product
expression = "1" if not poa_fields else " * ".join([f"!{field}!" for field in poa_fields])
arcpy.CalculateField_management(layer, "Product_poa", expression, "PYTHON")

 

 

0 Kudos
BlakeTerhune
MVP Regular Contributor

Please fix the indentation in this code.

0 Kudos
Shauna-RaeBrown
Frequent Contributor

#JasmineSpring, one thing you need to do after using any cursor, is you need to del the cursor.  Your code should look something like this...

import arcpy

# Get the selected layer
layer = arcpy.GetParameterAsText(0)

# Create a list of field names starting with "poa"
poa_fields = [field.name for field in arcpy.ListFields(layer) if field.name.startswith("poa")]

for field in poa_fields:
   with arcpy.da.UpdateCursor(layer, poa_fields) as cursor:
      for row in cursor:
         if row[0] is None:
            row[0]="1"
            cursor.updateRow(row)
del cursor

# Use the Field Calculator to calculate the product
expression = "1" if not poa_fields else " * ".join([f"!{field}!" for field in poa_fields])
arcpy.CalculateField_management(layer, "Product_poa", expression, "PYTHON")

 (see line 15). 

0 Kudos
JasmineSpring
Occasional Contributor

Thank you for your reply

I altered as above and the tool runs but the field doesnt calculate the product_poa field. Maybe the error is in the expression? I would like the field in the list to multiply and then be subtracted from 1.

eg . 1 - (field *field*field)    

The fields being taken from the list. 

Thank you very much

 

0 Kudos