Guide to repeated data, part 4: Cookbook

This article is part 4 of our series on repeat groups. See the bottom of this article for the other parts in this series.

Here are some tools you can use on repeated data to get the performance you need.

For many of these tools, they is just one method, and there can be lots of other ways to accomplish the same goal, so don't feel constrained to just use the methods listed here.

Table of Contents
  1. Mean average using sum() and count()
  2. Make field relevant if ANY repeat instance equals a certain value
  3. Make field relevant if ALL repeat instances equal a certain value
  4. Choice list from repeated field
  5. Filtered follow-up repeat group
  6. Data about repeat instance with a max value (e.g. get name of oldest household member)

1. Mean average using sum() and count()

A mean average is calculated by summing all values, and dividing that sum by the total number of values. For example, let's say you have this list of numbers:

1 2 8 9

The sum of those numbers is 20, and there are four numbers. So, the mean average is 5, since:

(1+2+8+9) 4=5

You can get the sum of all instances of a repeated field using the sum() function, and you can get the number of instances of that repeated field using the count() function. So, you can use those functions to calculate the average:

name calculation
rep_sum sum(${repeated_field})
rep_count count(${repeated_field})
rep_avg ${rep_sum} div ${rep_count}

2. Make field relevant if ANY repeat instance equals a certain value

The join() function can be used to create a list of values from a repeated field. The selected() function can check a space-separated list, and see if a certain value exists. You can combine these functions to create a space-separated list, and see if a certain value exists. For example, if a repeated field is called "is_pregnant", and you want want a field to be relevant if any instance of the field "is_pregnant" has a value of 1, then you can give that field this expression:

selected(join(' ', ${is_pregnant}), '1')

You can also divide it up using a calculate field, as demonstrated in this sample form.

To make the field relevant only if NONE of the repeated values equal 1, simply wrap the expression in the not() function:

not(selected(join(' ', ${is_pregnant}), '1'))

3. Make field relevant if ALL repeat instances equal a certain value

Let's say a field in the form should only be relevant if all household members are available. The repeated field "hh_available" has a value of 1 if they are available.

Outside of the repeat group, add a calculate field with this calculation

count-if(${hh_available}, not(selected(${hh_available}, '1')))

That will check each household member, and count the number of household members where for the field "hh_available", choice 1 was not selected. We'll call that field "num_not_avail".

If ${num_not_avail} has a value of 0, then it means all household members are available. If it has a value greater than 0, then it means at least one person is not available. So, if a field should only be relevant if everyone is available, it means it should only be relevant if "num_not_avail" has a value of 0:

${num_not_avail} = 0

4. Choice list from repeated field

This is accompanied by this sample form.

You cannot use repeated fields in choice labels. Instead, add a series of calculate fields that use the indexed-repeat() function to retrieve each potential choice label. Then, use those calculate fields in your choice list.

In the choice list, have the choice values start from 1, and be sequential. So, the first choice should have a value of 1, the second choice should have a value of 2, and so on. Each choice should have a filter that matches its value. Then, for the choice_filter, set it so the choice only appears if the filter is less-than-or-equal to the size of the repeat group, like this:

filter <= ${hh_size}

That way, it will hide blank choices.

To learn how to build on this and add additional filters, check out part 3 of our Guide to choice filters, Example 6. That support article also has other ways to work with repeated data in choice lists.

5. Filtered follow-up repeat group

This is accompanied by this sample form.

Let's say you have a repeat group that collects a list of household members. Then later, you want to cycle through those same household members in a new repeat group, but to only show eligible household members.

Within the second repeat group, add a regular group that uses the repeat index, and is only relevant if the household member is eligible, like this:

selected(${all_eligible}, ${eligible_index})

With this, the group will only be relevant if the ID of the household member is in the list of eligible IDs. Then, put all visible fields into that group. That way, the repeat group will still cycle through each household, but the enumerator will only be shown those that are actually eligible, hiding the ones that are not.

6. Data about repeat instance with a max value (e.g. get name of oldest household member)

This is accompanied by this sample form.

Let's say there is a repeat group that asks about a series of household members, and the repeat group asks for the age of each household member. Then, you have follow-up questions, but only for the oldest household member. You will need the index of the oldest household member, since you can use that with an indexed-repeat() function to retrieve data about them.

First, you need the max age. You can get that with the max() function. Add a calculate field outside of all repeat groups that retrieves that max age:

max(${hh_age})

You can then use that with the join-if() function to create a list of all indexes where the age of the household member matches that of the oldest member:

join-if(' ', ${hh_index}, ${hh_age} = ${max_age})

That will create a space-separated list of the indexes of oldest household member(s). If there is just one household member that is the oldest, then that will be a list with one item, and that is the index of the oldest member.

If you think there will be more than one household member with the same age, then you have two options. The easiest option is to just use the selected-at() function to retrieve the first household member that was entered with that age:

selected-at(${oldest_indexes}, 0)

For a more robust workflow, you can also create a choice list of all household members with that age, and have the enumerator select the oldest household member.

Once you have their index (demonstrated in the field “oldest_index”), you can use that to retrieve other information about them. For example, in the field "oldest_name" on row 36, the index is used to retrieve their name:

indexed-repeat(${hh_name}, ${hh_rep}, ${oldest_index})

More on repeat groups

  1. Repeat group basics: What repeat groups are, and how to use them.
  2. Using and referencing repeated data: How to use repeated data in other parts of your form.
  3. Nested repeat groups (advanced): How to use a repeat group inside of a repeat group.
  4. Cookbook: Various tools and examples of using repeat groups and functions you can use in your own forms to retrieve and generate the data you need.

Do you have thoughts on this support article? We'd love to hear them! Feel free to fill out this feedback form.

0 Comments

Please sign in to leave a comment.