Forum Discussion
A generalisation of the MAP lambda helper function
- Sep 08, 2024
This is a demonstration of the proposed MAP function used to solve a challenge provided by Oz_Sunray and Wyn Hopkins on data cleansing and vote counting. The key element of my solution is to build a table of validated votes for each voter ID and each candidate (i.e. an array of arrays - much the same as any other problem of interest). The formula is modularised using Lambda functions. They are not that pretty, but neither are they impossible to follow.
"Worksheet formula" = AggregateVotesλ( tblVOTES[VoterID], tblVOTES[[Vote1]:[Vote3]], weight, tblAvailable[AVAILABLE] )
which calls
/* "FUNCTION NAME: AggregateVotesλ" "DESCRIPTION: Aggregates all votes to candidate colors" */ /* "REVISIONS: Date Developer Description" " 08 Sep 2024 Peter Bartholomew Original Development" */ AggregateVotesλ = LAMBDA(voterID, votesCast, weight, available, LET( person, TOROW(UNIQUE(voterID)), votes, MAPλ(person, AssignVotesλ(voterID, votesCast, weight, available)), count, HSTACK(available, BYROW(votes, SUM)), return, TAKE(SORT(count, 2, -1), 4), return ) );
to build and aggregate the table of votes. This, in turn, calls another Lambda function to clean and validate the votes corresponding to a single voterID
/* "FUNCTION NAME: AssignVotesλ" "DESCRIPTION: Validates and assigns votes to candidate colors for a single voterID " */ /* "REVISIONS: Date Developer Description" " 08 Sep 2024 Peter Bartholomew Original Development" */ AssignVotesλ = LAMBDA(voterID, ballots, weight, available, LAMBDA(p, LET( // "In the case of duplicate ballots return first" votesCast, XLOOKUP(p, voterID, ballots), // "Remove invalid and repeated votes" valid, COUNTIFS(available, votesCast), distinct, EXPAND(UNIQUE(FILTER(votesCast, valid), TRUE), , 3, ""), // "Assign votes to candidate colours" assigned, BYROW((distinct = available) * weight, SUM), assigned ) ) );
I took the problem from Wyn's recording
https://www.youtube.com/watch?v=FIcxyLqzWcE
This is a demonstration of the proposed MAP function used to solve a challenge provided by Oz_Sunray and Wyn Hopkins on data cleansing and vote counting. The key element of my solution is to build a table of validated votes for each voter ID and each candidate (i.e. an array of arrays - much the same as any other problem of interest). The formula is modularised using Lambda functions. They are not that pretty, but neither are they impossible to follow.
"Worksheet formula"
= AggregateVotesλ(
tblVOTES[VoterID],
tblVOTES[[Vote1]:[Vote3]],
weight,
tblAvailable[AVAILABLE]
)
which calls
/* "FUNCTION NAME: AggregateVotesλ"
"DESCRIPTION: Aggregates all votes to candidate colors" */
/* "REVISIONS: Date Developer Description"
" 08 Sep 2024 Peter Bartholomew Original Development"
*/
AggregateVotesλ
= LAMBDA(voterID, votesCast, weight, available,
LET(
person, TOROW(UNIQUE(voterID)),
votes, MAPλ(person, AssignVotesλ(voterID, votesCast, weight, available)),
count, HSTACK(available, BYROW(votes, SUM)),
return, TAKE(SORT(count, 2, -1), 4),
return
)
);
to build and aggregate the table of votes. This, in turn, calls another Lambda function to clean and validate the votes corresponding to a single voterID
/* "FUNCTION NAME: AssignVotesλ"
"DESCRIPTION: Validates and assigns votes to candidate colors for a single voterID " */
/* "REVISIONS: Date Developer Description"
" 08 Sep 2024 Peter Bartholomew Original Development"
*/
AssignVotesλ
= LAMBDA(voterID, ballots, weight, available,
LAMBDA(p,
LET(
// "In the case of duplicate ballots return first"
votesCast, XLOOKUP(p, voterID, ballots),
// "Remove invalid and repeated votes"
valid, COUNTIFS(available, votesCast),
distinct, EXPAND(UNIQUE(FILTER(votesCast, valid), TRUE), , 3, ""),
// "Assign votes to candidate colours"
assigned, BYROW((distinct = available) * weight, SUM),
assigned
)
)
);
I took the problem from Wyn's recording
https://www.youtube.com/watch?v=FIcxyLqzWcE
Finally getting to this one!
In re: Wyn's challenge.
Here's my take:
=LET(
flat, UnPivotMλ(
tblVOTES[VoterID],
weight,
tblVOTES[[Vote1]:[Vote3]]
),
colors, TAKE(UNIQUE(flat), , -1),
agg, SORT(GROUPBY(colors, colors, COUNTA, 0, 0), 2, -1),
TAKE(agg, 4)
)
//UnPivotMλ being:
UnPivotMλ = LAMBDA(rows, columns, values,
LET(
i, ROWS(rows),
j, COLUMNS(rows),
c, COLUMNS(columns),
s, TOCOL(SEQUENCE(, j) * SEQUENCE(c, , 1, 0)),
row_labels, WRAPROWS(TOCOL(CHOOSECOLS(rows, s)), j),
attribute, TOCOL(CHOOSEROWS(columns, SEQUENCE(i, , 1, 0))),
v, TOCOL(values),
HSTACK(row_labels, attribute, v)
)
)