# Field Calculator - How to evaluate and sum multiple fields?

I'll do my best to describe the problem - my main issue isn't so much the python code but rather the logic I'm using.

The file I'm working on is a polygon shapefile with forest attribute data. In the attribute table, each polygon has 5 fields that describe tree species present (SP1-5) and a percentage that each species represents in each polygon (SP1-5_PER). Below is a picture of the attribute table I'm working with. I'm trying to use field calculator to sum the percent of coverage that is composed of coniferous trees, in each polygon. Ie, this polygon has 50% coniferous, whereas that one has 80%. etc etc etc.

Here is what my code in field calculator looks like:

``````def percvr(sp1,per1,sp2,per2,sp3,per3,sp4,per4,sp5,per5):
sum = 0
if (sp1 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb"  or "Fa" or "Fd"):
sum=sum+per1
if (sp2 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
sum=sum+per2
if (sp3 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
sum=sum+per3
if (sp4 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
sum=sum+per4
if (sp5 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
sum=sum+per5
return sum
``````

esri_field_calculator_splitter

``````percvr( !SP1!, !SP1_PER!, !SP2!, !SP2_PER!, !SP3!, !SP3_PER!, !SP4!, !SP4_PER!, !SP5!, !SP5_PER!)
``````

The above text may not be overly clear so I included an image to show indenting: Basically, what I want it to do is, if the SPn field corresponds to one of the above tree codes, add the number from the corresponding percentage field to the sum. If the tree code does not match one of the above, do nothing and move on to the next case. Finally, output the sum to the field.

The issue that seems to come up is that this function seems to be adding all percent cover no matter what so that the resulting values are all 100%

• Perhaps you should be using elif and else instead of multiple if statements? – GISKid Nov 10 '14 at 18:07
• I'm sorry, I added the wrong image and deleted the link for the correct one. Plz reject my edits if you can or add correct link. – SS_Rebelious Nov 10 '14 at 18:13
• don't you need a separate sum for each species? Sounds like adding to 100% based on percentage of all species is doing just what you specified! – jbchurchill Nov 10 '14 at 18:20
• I don't want to add all species, I just want to add those that are coniferous. – Dave Nov 10 '14 at 18:39
• I'd start with adding all your coniferous tree types to a list, and then checking against the list rather than using all those OR statements. For example, `coniferous = ["Sw", "Se", "Sb",...]` – Dan C Nov 10 '14 at 19:50

Well, with the help of a friend I got the code to work. Here's what it looked like in the end:

``````def percvr(sp1,per1,sp2,per2,sp3,per3,sp4,per4,sp5,per5):
sum = 0
if (sp1 == "Sw" or sp1== "Se"  or sp1== "Sb" or sp1== "P" or sp1== "Pl" or sp1== "Pj" or sp1== "Pa" or sp1== "Pf" or sp1== "Fb" or sp1== "Fa" or sp1== "Fd"):
sum=sum+per1
if (sp2 == "Sw" or sp2== "Se" or sp2== "Sb" or sp2== "P" or sp2== "Pl" or sp2=="Pj" or sp2=="Pa" or sp2== "Pf" or sp2=="Fb" or sp2== "Fa" or sp2== "Fd"):
sum=sum+per2
if (sp3 == "Sw" or sp3 == "Se" or sp3 == "Sb" or sp3 == "P" or sp3 == "Pl" or sp3 == "Pj" or sp3 == "Pa" or sp3 == "Pf" or sp3 == "Fb" or sp3 == "Fa" or sp3 == "Fd"):
sum=sum+per3
if (sp4 == "Sw" or  sp4 == "Se" or sp4 == "Sb" or sp4 == "P" or sp4 == "Pl" or sp4 == "Pj" or sp4 == "Pa" or sp4 == "Pf" or sp4 == "Fb" or sp4 == "Fa" or sp4 == "Fd"):
sum=sum+per4
if (sp5 == "Sw" or sp5 ==  "Se" or sp5 ==  "Sb" or sp5 ==  "P" or sp5 ==  "Pl" or sp5 ==  "Pj" or sp5 ==  "Pa" or sp5 ==  "Pf" or sp5 ==  "Fb" or sp5 ==  "Fa" or sp5 ==  "Fd"):
sum=sum+per5
return sum

__esri_field_calculator_splitter__
percvr( !SP1!, !SP1_PER!, !SP2!, !SP2_PER!, !SP3!, !SP3_PER!, !SP4!, !SP4_PER!, !SP5!, !SP5_PER!)
``````

It's not very clean but it works - everything is summed properly. Ultimately, I think achieving the same goal with a list would be much cleaner. Thank you very for your help and the suggestions!

• Dave, have you considered lists? There is a value in [list] boolean operator (case sensitive). For example Valid = ["Sw","Se","Sb"] then the conditional if sp1 in Valid: also consider using elif instead of if for subsequent statements - interesting things can happen if multiple statements are satisfied, using elif ensures only one case is met prior to return – Michael Stimson Nov 11 '14 at 5:32

You could try normalizing the table.

Basically, you create a separate table with ForestCoverID, Species, and SpeciesPercent columns where ForestCoverID is the key to link back to the individual polygons.

Each ForestCover polygon will then have up to 5 rows in the table, though, likely less as you don't need to record the 0s.

Then you only need to query on one column instead of 5 and it is easier to maintain as well.

Use 2 lists as function arguments

``````def percvr(listOfSp,listOfPerc):
conif,sum=('Sw,"Se'..),0
for sp in listOfSp:
if sp in ('Sw',"Se'..):
i=listOfSp.index(sp)
sum+=listOfPerc[i]
``````