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.

Attribute Table

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"):
    if (sp2 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
    if (sp3 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
    if (sp4 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
    if (sp5 == "Sw" or "Se" or "Sb" or "P" or "Pl" or "Pj" or "Pa" or "Pf" or "Fb" or "Fa" or "Fd"):
    return sum


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%

  • 1
    Perhaps you should be using elif and else instead of multiple if statements?
    – GISHuman
    Nov 10, 2014 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. Nov 10, 2014 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! Nov 10, 2014 at 18:20
  • I don't want to add all species, I just want to add those that are coniferous.
    – Dave
    Nov 10, 2014 at 18:39
  • 2
    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, 2014 at 19:50

3 Answers 3


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"):
  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"):
  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"):
  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"):
  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"):
  return sum

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 Nov 11, 2014 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):
 for sp in listOfSp:
  if sp in ('Sw',"Se'..):

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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