Calculate average based on previous entries

Is it possible to display a calculated average value based on previous inputs? Here is an example scenario:
Sources of income are captured in different fields: Src1, Src2, Src3, Src4, Src5 and Src6.
(Src1, 2 and 3 are options of a multi-select question. Src4, 5 and 6 are individual questions)
Average has to be calculated only for the income sources that have a value. So if only Src1, Src2, Src4 and Src6 have values, then Average income= (Src1+Src2+Src4+Src6)/4

This is one way I can think of:
Step 1: Increment a field (Total) by 1 everytime an income source field is entered (Problem: Not sure how to do that)
Step 2: Create a calculate field and use the following formula to calculate average:
(coalesce(${src1}, 0) + Coalesce(${src2}, 0) + coalesce(${src3}, 0) + Coalesce(${src4}, 0) +coalesce(${src5}, 0) + Coalesce(${src6}, 0))/Total

Question: Is there a better way to do this? If not, how should I calculate the 'Total' field? It needs to increase by 1 everytime src1, src2, src3 etc are populated.

Welcome to the ODK forum, @ssinha!

Your approach seems reasonable to me. To calculate the total, you could try a calculate with this:

if(${Src1}='', 0, 1) + if(${Src2}='', 0, 1) + if(${Src3}='', 0, 1) ...

I haven't tried this myself, but the idea is f you have a value for SrcN, then you set a value of 1.


Another way to do this is leverage some of the more obscure behavior of XPath... this actually works too (and is a bit shorter):

${Src1}!='' + ${Src2}!='' + ${Src3}!='' + ...

basically the boolean operator != will return true or false, which is converted to 1/0 when used in an arithmetic expression. From XPath1.0:

3.5 Numbers

  • The numeric operators convert their operands to numbers as if by calling the number function.

and number():

The number function converts its argument to a number as follows:

  • boolean true is converted to 1; boolean false is converted to 0

Thank you so much for the prompt response @yanokwa and @Xiphware! I will try these options out and keep you updated on whether that worked.