8

I would like to calculate a field (short integer) using other fields (short integer) present in the table. In some cases these fields may have null values for one or more of the fields. For example, the new field name is 'total' and total is based upon adding field1 + field2 + field3. Some records (rows) have values for field1, field2, and field3, but some rows only have values for field1 and field2, then field3 is null. Do I need to go and replace all null values with a numeric value? Or, is there some workaround within the VB or python script?

I'm using ArcMap 10.1

I've used a python example from below and have been unable to get it to work. Here is the code I'm using:

#calculate new field 'summed' in feature class 'test'
inFeatures='test'
fieldName01='summed'
exSummed = "stack(!field01!+!field02!+!field03!)"
codeBlock = "def stack(*args):
    return sum(filter(None, args))"

arcpy.CalculateField_management(inFeatures, fieldName01, exSummed, "PYTHON", codeBlock)

where 'summed' is the field (short) I would like to populate and field01, field02, field03 are all short integers which may or may not have NULL's present.

I receive an error when I run this...

enter image description here

1
  • 1
    2 problems in the 2014-Feb-28 update: (a) The EOL syntax error is because of the line break. You need to either triple quote the block, or since it's so short turn it into a one liner: codeBlock = "def stack(*args): return sum(filter(None, args))". (b) In exSummed = you are concatenating or adding the fields together before passing them to your stack function. Needs to be "stack(!item1!, !item2!, !item3!)" Jun 17, 2015 at 20:58

3 Answers 3

12

A nice Pythonic way of tackling this is to use the filter function, which takes two inputs: the value you'd like to exclude, and the input object (any interable). After that, just sum the result:

def stack(*args):
    return sum(filter(None, args))
1
  • This is a great answer "scw". I'm still finding my way in Python and this is a really neat way of summing up the contents of a list whilst skipping no data.
    – Hornbydd
    Jun 4, 2013 at 15:32
5

@ustroetz answer is almost correct. However, it won't necessarily give you the correct results.

When you mutate the list while iterating over it, you may skip some values.

For example, if your list is defined as such:

mylist = [None, 3,4,5,6,7, None, None, 4,65,23,6, None]

and you use this code:

for item in myList:
  if item is None:
   myList.remove(item)

Then your resulting mylist will be:

[3, 4, 5, 6, 7, 4, 65, 23, 6, None]

Please see if statement in loop not working and Unexpected behaviour in looping a list (I asked the second question when I tried to replicate the above code) on Stackoverflow which cover similar issues.

@Gareth Latty's response describes using list comprehension to get the correct answer.

So, if we modify @ustroetz's answer, you should put the following as your pre-logic code:

def stack(*args):
  myList = list(args)
  myList [item for item in mylist if item]
  return sum(myList)
2
  • +1 for the example - I didn't realize that could happen...I like the [x for x in y] operation. Jun 4, 2013 at 15:25
  • 1
    +1 for the example of an unwanted results. There's a syntax error in def stack though, the 2nd myList line is missing =. Also the list comprehension can be simplified to [item for item in mylist if item] -- because if item is functionally identical to if item is not None. See docs.python-guide.org/en/latest/writing/style/… Jun 17, 2015 at 20:46
0

The following python field calculator code should do the job:

total =

stack( !field1!, !field2!, !field3!)

Pre-Logic Script Code:

def stack(*args):
 myList = list(args)
 for item in myList:
  if item is None:
   myList.remove(item)
 return sum(myList)
1
  • mutating the list while iterating it will possibly skip results. See my answer.
    – Fezter
    Jun 4, 2013 at 6:43

Your Answer

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

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