Calculate Field Tool and Python

8821
16
07-12-2011 06:07 AM
Corey_C_Denninger
New Contributor
I'd think this one should be easy. 
How do I use my input parameters, to automatically update my Calculate Field expression, within a Python script?  I thought I had it, but I receieve an error.

In my script I would like portions of the expression in the Calculate Field line to change as my input parameters change.  If I force the expression like this, it works:
"( !SUM_POP10! / !SUM_SUM_POP10! )*100", "PYTHON")

But I need both of the fields (either side of the "/" line) in that expression to change based upon one of my input paramters I choose, here:  
popfield = gp.GetParameterAsText(2) #population field

Here is how I have it and where I beleive the Error is coming from; not sure what it doesn't like:
arcpy.CalculateField_management(outputfc, percentfield, '"('+str(popfield)+'/SUM_'+str(popfield)+')*100"', "PYTHON")


Again, as the "popfield =" paramter changes, so does the expression.  So as I choose a new "SUM_POPxx" field, the expression automatically changes with it.

I'd appreciate any assistance.  Thank you.
Tags (2)
0 Kudos
16 Replies
StacyRendall1
Occasional Contributor III

arcpy.CalculateField_management(outputfc, percentfield, '"('+str(popfield)+'/SUM_'+str(popfield)+')*100"', "PYTHON")


Again, as the "popfield =" paramter changes, so does the expression.  So as I choose a new "SUM_POPxx" field, the expression automatically changes with it.


you probably need to attach ! to either side of your popfield, i.e.:
popfield = gp.GetParameterAsText(2) #population field

popfield_new = '!'+popfield+'!'

arcpy.CalculateField_management(outputfc, percentfield, '"('+popfield_new+'/SUM_'+popfield_new+')*100"', "PYTHON")


Let me know how you get on...
0 Kudos
KimOllivier
Occasional Contributor III
My suggestion is to use a cursor to calculate fields if you are in a Python script. Leave CalculateField for the modelbuilders!

Since CalculateField just runs a cursor, the speed will be the same.

A cursor can be much easier to program, and read.
There are no special characters to escape such as bangs!
It is much easier to debug.
You can trap 'unexpected data' such as nulls or divide by zero without a complete crash which you will get with CalculateField.
You can use a selection query in opening the cursor to limit the records more easily than having to use a layer definition.
0 Kudos
Corey_C_Denninger
New Contributor
Thanks Kim.  I'd agree with that, except like many GIS folk, my scripting needs some work.  Since the script already exists in its current state, I'd rather use it that way.

Stacy - I added it just as you had it and no luck.  Now I get an the following ERROR:  "The value type is incompatible with the field type."  Hmmm...
0 Kudos
StacyRendall1
Occasional Contributor III
OK. Not sure what is happening, but this is what debugging is all about. To find the problem you need to rigorously eliminate every possibility. Check everything is as you expect it, check more, and check again! Arcpy scripts seldom work straight away...

The message that it is producing leads me to think that you have made the percent field an incompatible type with the data that is being calculated. I.e. percentfield is a short integer but the output is a float. If that doesn't help, try the steps outlined below (if it does, look through them anyway, might help you next time there is an issue).

Essentially, the '"('+popfield_new+'/SUM_'+popfield_new+')*100"' part of your calculate field statement should look exactly like it does when you force the statement.

You can check if your new popfield is looking right with an:
arcpy.AddMessage("Pop. Field:"+popfield_new)

placed just before the Calculate Field statement, so it should print !SUM_POP10!, if SUM_POP10 is your input.

If that looks OK, replace the AddMessage with this one:
arcpy.AddMessage('"('+popfield_new+'/SUM_'+popfield_new+')*100"')

which should give you "( !SUM_POP10! / !SUM_SUM_POP10! )*100" if SUM_POP10 is your input.

If that looks OK, but it still fails, do the calculate field in Arc, making sure to use the same fields you are passing in the script.
0 Kudos
Corey_C_Denninger
New Contributor
Stacy - Thanks for the info.  I will try all that.  Just a note on the ERROR message, I thought the same thing you did about wrong field type, but it is the correct type and works fine when I just hard code the script....it populates the field with the expected values...so that ERROR msg is strange and perhaps plain wrong.  I'll let ya know how it all goes.  Thanks again.
0 Kudos
markdenil
Occasional Contributor III
First off:  '"('+popfield_new+'/SUM_'+popfield_new+')*100"'
has nested single quotes that will confuse matters. You need to escape the double quotes so they don't form a pair, and thus won't nest the inner single quotes.

Next, it would seem to me that with a number of fields names like SUM_POPxx,
the xx is the only real variable.

for each in [10, 20, 30]:
    firstField = "SUM_POP" + str(each)
    nextField = "SUM_" + firstField
    calcString = '\"(!' + firstField + '!/!' + nextField + '!)*100\"'
    print calcString
    arcpy.CalculateField_management(outputfc, percentfield, calcString, "PYTHON")


M.Denil
0 Kudos
Corey_C_Denninger
New Contributor
Thanks Denil.  All of these solutions seem to work in one way or another.  What I am experiencing each time now is that error msg that implies my field value type is wrong or incompatiable. This is just not the case.  I am not dividing by any zeros, but there are <Null> values and perhaps that is the issue (although it shouldn't be). 
Again, if I open the feature class table manually and use Field Calculator to do the formula, it works just fine, no isses...but in the script....ERROR.

ERROR MSG: "<class 'arcgisscripting.ExecuteError'>: ERROR 999999: Error executing function.
The value type is incompatible with the field type. [PER_POP_WUCA4_10]
Failed to execute (CalculateField).

Failed to execute (CalcPercent)."


Any ideas?
0 Kudos
StacyRendall1
Occasional Contributor III
Yo; found the problem. You have so many quotes in your calculation, they are actually messing it up, and I think the thing being returned is being converted into a string - hence the error, as you are adding it to a number field.

What you need to do is get rid of the overall quotes. Using the method that @mdenil showed, where calcString = something is specified beforehand then printed, you were initially printing:
calcString = "(!SUM_POP10!/!SUM_SUM_POP10!)*100" (itself a string)


but you actually just want:
calcString = (!SUM_POP10!/!SUM_SUM_POP10!)*100 (it is still a string, just not wrapped in excessive quotes)


So, the code from my first post now becomes:
popfield = arcpy.GetParameterAsText(2) #population field

popfield_new = '!'+popfield+'!'

arcpy.CalculateField_management(outputfc, percentfield, '('+popfield_new+'/SUM_'+popfield_new+')*100', "PYTHON")



I also just noticed that at one stage in your original post you are using gp, and another you are using arcpy. I don't really understand all the layers of arccrap, but it might be worth trying to get rid of anything referring to gp, and just using arcpy. So, arcpy.GetParameterAsText(), arcpy.AddMessage(), etc.

Let me know how it goes...
0 Kudos
Corey_C_Denninger
New Contributor
You're a riot Stacy!!!  😄  Thanks for the assistance.

We are soooo close.  I've been trying to modify the paramter and/or the formula to make it work, but I am clearly missing something.  See ERROR:

"<class 'arcgisscripting.ExecuteError'>: ERROR 000539: Error running expression: (44266.1586547927/SUM_44266.1586547927)*100 <type 'exceptions.SyntaxError'>: invalid syntax (<string>, line 1)
Failed to execute (CalculateField)."

It is obviously including the word "SUM_" into the math, and there fore not only trying to combine and divide string with numbers, but still using the first field to do that math for the denominator, which is obviously incorrect:  44266.1586547927/SUM_44266.1586547927)*100
0 Kudos