Search code examples
google-sheetsformulasarray-formulas

Count selected elements for each line and create an arrayformula that groups by number of counts


We have asked users:

What to do with the money?
[ ] paint the bridge
[ ] rebuild the school
[ ] keep the money
[ ] Other : [____________________]

Here is the spreadsheet with their answers:

     A          B
1    Name       Choices
2    Lilia      paint the bridge, rebuild the school, keep the money
3    Paul       rebuild the school, paint the bridge, do something else
4    Margerite  keep the money, I don't know, do what you want
5    John       paint the bridge
...
800

I want a formula that output the number of official choices (excluding other) picked per user.

With the first 4 rows of data, the formula would output this table:

D                           E
Nbr of choices a user made  Frequency (Nbr of users who made these choices)
0                           0
1                           2
2                           1
3                           1

Couldn't find a way to get this right from a single formula. For a starter, I wanted to split each line (of B2: B) by "," but couldn't find a way to apply a fn (split) to each line in an formula...

Even with 800 rows of data (B2:B), the resulting table (D2:E5) would always be 4 rows long plus titles (and two column wide)

I could do this in C2, and replicate manually with the "+" corner icon...

=countif(B2;"*rebuild the school*")+countif(B2;"*keep the money*")+countif(B2;"*paint the bridge*")

And then do in E2:

=arrayformula(countif(C2:C;D2:D5))

But I'd like to generate the table of frequencies in one formula, without any manual action (without C column).

So I am looking for a way to "map" the first function to each row, put this in the second fn.

ANSWER by Akshin Jalilov EXPLAINED

This is the answer by Akshin Jalilov, but shorter (and with international notations)

=ARRAYFORMULA(COUNTIF(ARRAYFORMULA(IF(B2:B="";;COUNTIF(ARRAYFORMULA
(IFERROR(IF(FIND("paint the bridge";B2:B);Row(B2:B);0)));"="&row(B2:B))
+COUNTIF(ARRAYFORMULA(IFERROR(IF(FIND(
"rebuild the school";B2:B);Row(B2:B);0)));"="&row(B2:B))
+COUNTIF(ARRAYFORMULA(IFERROR(IF(FIND(
"keep the money";B2:B);Row(B2:B);0)));"="&row(B2:B))));"="&D2:D5))

Step1:

IF(FIND("rebuild the school";B2:B);Row(B2:B);0)

This means, for each row (B2:B) find "rebuild the school". If you find it, return the number of the row, otherwise, return 0.

Step2:

=ARRAYFORMULA(IFERROR(Step1))

Wrap this in an ARRAYFORMULA so that you return the results for each row. I think IFERROR is there to prevent an error from stopping the process.

Step3:

=ARRAYFORMULA(IF(B2:B="";;COUNTIF(ARRAYFORMULA(IFERROR(IF(FIND("paint the bridge";B2:B);Row(B2:B);0)));"="&row(B2:B))+countif(Step2)+countif(ARRAYFORMULA(IFERROR(IF(FIND("keep the money";B2:B);Row(B2:B);0)));"="&row(B2:B))))

This will count valid votes made by each users. This is equivalent to C2 formula referred in my manual process. But is it now part of a single global formula.

Step4: Lastly, the rest of the formula counts frequencies of each voting count possibilities.


Solution

  • I know this formula is large but this is the closest I got to what you want. Now to make it easy, name your responses range "Responses". I assume it is B2:B.

    Here is the formula:

    =ARRAYFORMULA(Countif(ARRAYFORMULA(IF(Responses="",,COUNTIF(VLOOKUP(row(Responses),({ARRAYFORMULA(Row(Responses)),ARRAYFORMULA(IFERROR(IF(FIND("paint the bridge",Responses),Row(Responses),0))),ARRAYFORMULA(IFERROR(IF(FIND("rebuild the school",Responses),Row(Responses),0))),ARRAYFORMULA(IFERROR(IF(FIND("keep the money",Responses),Row(Responses),0)))}),2),"="&row(Responses))+COUNTIF(VLOOKUP(row(Responses),({ARRAYFORMULA(Row(Responses)),ARRAYFORMULA(IFERROR(IF(FIND("paint the bridge",Responses),Row(Responses),0))),ARRAYFORMULA(IFERROR(IF(FIND("rebuild the school",Responses),Row(Responses),0))),ARRAYFORMULA(IFERROR(IF(FIND("keep the money",Responses),Row(Responses),0)))}),3),"="&row(Responses))+COUNTIF(VLOOKUP(row(Responses),({ARRAYFORMULA(Row(Responses)),ARRAYFORMULA(IFERROR(IF(FIND("paint the bridge",Responses),Row(Responses),0))),ARRAYFORMULA(IFERROR(IF(FIND("rebuild the school",Responses),Row(Responses),0))),ARRAYFORMULA(IFERROR(IF(FIND("keep the money",Responses),Row(Responses),0)))}),4),"="&row(Responses)))),"="&D2:D5))
    

    Here is an example if how it works. I am not sure which one exactly you wanted so added both