0

I was successful in adding multiple fields but had trouble running multiple field calculations in a loop. Now what I want is loop through these existing fields listed in mult_fields variable and fill values in the fields newly created through the div_fields variable. I was hoping something like the following would work, rather than using search cursors.

import arcpy
from arcpy import env


# set the environments
arcpy.env.overwriteOutput = True
env.workspace = "C:\\WORKSPACE\\mm_agallocation.gdb"
inFeature = "myFeature"
div_fields = ("divpa_whea"  , "divpa_maiz", "divpa_barl", "divpa_sorg",
                  "divpa_sorg", "divpa_grou","divaa_whea", "divaa_maiz", "divaa_barl", 
                  "divaa_sorg", "divaa_sorg", "divaa_grou")
for i in div_fields:
    arcpy.AddField_management(myFeature, i, "DOUBLE", "", "", "", "", "NULLABLE")

mult_fields = ("mpa_whea"  , "mpa_maiz", "mpa_barl", "mpa_sorg",
               "mpa_sorg", "mpa_grou","maa_whea","maa_maiz", 
               "maa_barl", "maa_sorg", "maa_sorg", "maa_grou")

# all field names given in 'mult_fields' are already in "myFeature"
for i in div_fields:
    for k in mult_fields:
        expression = "!k! * !k!"
        arcpy.CalculateField_management(inFeature, i, expression, "PYTHON")

I however get the following error. I'd imagine it is the way I am specifying the expression that is giving me the error.

Traceback (most recent call last):
  File "<input>", line 6, in <module>
  File "C:\Program Files (x86)\ArcGIS\Desktop10.0\arcpy\arcpy\management.py", line 2727, in CalculateField
    raise e
ExecuteError: ERROR 000539: Invalid field mult_fields
Failed to execute (CalculateField)
5
  • 1
    Yes, I think it's the way you're referring to your iteration variables in side a Python string. Why not use a Update Cursor? The newer ones in arcpy.da are pretty fast. Nov 20 '15 at 23:04
  • Thanks! you are right, but I have arcgis 10.0 the arcpy.da came after that..
    – yanes
    Nov 20 '15 at 23:05
  • 1
    You have provided two pieces of code but not a working code snippet (that starts with import arcpy) so that we can quickly test to try and reproduce. With that, or to help create that, I would start by printing out the contents of div_fields and mult_fields prior to their last usage.
    – PolyGeo
    Nov 20 '15 at 23:05
  • 1
    Rather than k * k you may want to consider using k ** 2, once you get the Python Parser bit sorted out.
    – PolyGeo
    Nov 20 '15 at 23:12
  • thanks I've edited the question accordingly. I'm going to try your suggestion.
    – yanes
    Nov 20 '15 at 23:15
2

As it currently stands, your nested for loops are doing something akin to this:

div_fields = ["f1", "f2", "f3"]

mult_fields = ["g1", "g2", "g3"]

for t,i in enumerate(div_fields):
    for k in mult_fields:
        print("{}Calcing field {} with {}".format("\t"*t, i, "'!{0}! * !{0}!'".format(k)))
>>>
Calcing field f1 with '!g1! * !g1!'
Calcing field f1 with '!g2! * !g2!'
Calcing field f1 with '!g3! * !g3!'
    Calcing field f2 with '!g1! * !g1!'
    Calcing field f2 with '!g2! * !g2!'
    Calcing field f2 with '!g3! * !g3!'
        Calcing field f3 with '!g1! * !g1!'
        Calcing field f3 with '!g2! * !g2!'
        Calcing field f3 with '!g3! * !g3!'

This is probably not what you want (after all, each of the 12 fields is being overwritten 12 times--you're calling Calculate Field 144 times!). I'm assuming you want your wheat fields to be calculated with wheat, sorghum with sorghum, etc. To solve this, use zip():

for t,(i,k) in enumerate(zip(div_fields, mult_fields)):
    print("{}Calcing field {} with {}".format("\t"*t, i, "'!{0}! * !{0}!'".format(k)))
>>>
Calcing field f1 with '!g1! * !g1!'
    Calcing field f2 with '!g2! * !g2!'
        Calcing field f3 with '!g3! * !g3!'

As @Paulo pointed out, you are hardcoding your k variable, which means that Calculate Field is attempting to find a field named k. You don't need to wrap it in quotes, so here it is with your data now:

for i,k in zip(div_fields, mult_fields):
   arcpy.CalculateField_management(inFeature, i, "!{0}! * !{0}!".format(k), "PYTHON_9.3")
   # or "!{}! ** 2".format(k)

As a tip, you'll probably find it simpler to work with if you use more descriptive variable names. Reserve i,j,k for counters. Since your list is named div_fields, iterate over it with for div_field in div_fields or similar.

1
  • This works beautifully, thank you! I am now well educated about zip
    – yanes
    Nov 21 '15 at 1:25
1

I think you want to change expression = "!k! * !k!" to

expression = "'!" + k + "! * !" + k + "!'"
3
  • it gave me invalid syntax..I'll try wrapping it with a double quote.
    – yanes
    Nov 20 '15 at 23:22
  • 2
    @yanes, It's a bit easier to work with if you use str.format(): "'!{0}! * !{0}!'".format(k)
    – Paul
    Nov 20 '15 at 23:35
  • 1
    Ah, edited it so that the string would contain the single quotes. Though the nice string-formatting in the comment here by @Paul is perhaps more elegant :) Nov 21 '15 at 3:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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