I occasionally create fictional elections for fun and experiment with different methods of doing them. This time, I did an election for the presidency of a country, and I planned to carry it out with a Condorcet method. For those who aren’t familiar, a Condorcet method is any election system that declares the candidate who can beat all of their competitors, or more of the other candidates than anyone else, the winner. This winner is the Condorcet winner. I created a way to calculate who would be the Condorcet winner with a bunch of tables within my spreadsheet.
Here’s an image to help explain things, the first of two. It contains the row and column values.
This first table contains several columns, corresponding to the election candidates and their supporters. Each candidate’s supporters have distinct preferences for which candidate they would like to win. The candidate who is named in the top rows is the first preference of their voters. Beneath them are all the other candidates. At the bottom is the number of voters whose first preference is the candidate whose name is at the top of the column.
CONDORCET METHODS | Voters for Melian | Voters for Finwio | Voters for Kunlang | Voters for Lobbens | Voters for Grunxi | Voters for Dorekori | Voters for Tebulis | Voters for Edelän | Voters for Limbagge | Voters for Tanthani | Voters for Salmond |
---|---|---|---|---|---|---|---|---|---|---|---|
Preference 1 | Melian | Finwio | Kunlang | Lobbens | Grunxi | Dorekori | Tebulis | Edelän | Limbagge | Tanthani | Salmond |
Preference 2 | Kunlang | Tebulis | Melian | Kunlang | Tanthani | Tebulis | Dorekori | Melian | Melian | Lobbens | Dorekori |
Preference 3 | Finwio | Salmond | Lobbens | Tanthani | Lobbens | Finwio | Finwio | Kunlang | Lobbens | Kunlang | Tebulis |
Preference 4 | Edelän | Melian | Tanthani | Edelän | Kunlang | Salmond | Salmond | Limbagge | Kunlang | Melian | Melian |
Preference 5 | Limbagge | Edelän | Edelän | Melian | Melian | Limbagge | Melian | Tanthani | Edelän | Limbagge | Edelän |
Preference 6 | Lobbens | Kunlang | Limbagge | Limbagge | Limbagge | Melian | Tanthani | Lobbens | Tanthani | Tebulis | Finwio |
Preference 7 | Tanthani | Lobbens | Grunxi | Salmond | Edelän | Lobbens | Edelän | Salmond | Finwio | Edelän | Kunlang |
Preference 8 | Tebulis | Dorekori | Finwio | Grunxi | Finwio | Tanthani | Limbagge | Finwio | Salmond | Salmond | Tanthani |
Preference 9 | Salmond | Tanthani | Salmond | Finwio | Salmond | Edelän | Lobbens | Tebulis | Tebulis | Grunxi | Limbagge |
Preference 10 | Grunxi | Grunxi | Tebulis | Tebulis | Tebulis | Kunlang | Kunlang | Grunxi | Dorekori | Finwio | Lobbens |
Preference 11 | Dorekori | Limbagge | Dorekori | Dorekori | Dorekori | Grunxi | Grunxi | Dorekori | Grunxi | Dorekori | Grunxi |
Original apportionment | 146904 | 11791 | 39631 | 34314 | 60865 | 151989 | 203284 | 12238 | 57745 | 23282 | 353 |
Beneath that is another table. It contains all of the votes each candidate would get, based on the preferences in the first table, if they were pitted against each other in a series of one-on-one contests. The candidate whose name is listed in every column at the top of the spreadsheet is pitted against the candidates whose names are in the rows on the left. In each cell within each column in the imaged table, the votes for the candidate listed at the top of the column are counted up. There’s a conditional formatting rule that turns the cell blue if the candidate has a majority of votes. Beneath all the candidates are a set of four rows. The first row lists how many times they got a majority of votes, the second lists the average number of votes they received, and the last one ranks them in descending order, with the candidate with the most victories getting the rank of 1. Where a candidate would be pitted against themself, that cell is represented with “Candidate vs self” in markdown.
CANDIDATE MATCHUPS (ORIGINAL) | Melian | Finwio | Kunlang | Lobbens | Grunxi | Dorekori | Tebulis | Edelän | Limbagge | Tanthani | Salmond | Win count against candidate |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs Melian | Candidate vs self | 367064 | 158093 | 118462 | 60866 | 355626 | 367417 | 46552 | 244049 | 118462 | 198447 | 0 |
vs Finwio | 375332 | Candidate vs self | 374979 | 228076 | 158093 | 378908 | 378908 | 228429 | 228076 | 228076 | 70187 | 4 |
vs Kunlang | 584303 | 367417 | Candidate vs self | 531480 | 60866 | 367417 | 367417 | 379655 | 413018 | 473735 | 367417 | 5 |
vs Lobbens | 623934 | 514320 | 210916 | Candidate vs self | 60866 | 367417 | 367417 | 374569 | 572512 | 311813 | 367417 | 4 |
vs Grunxi | 681530 | 584303 | 681530 | 681530 | Candidate vs self | 425162 | 607584 | 681530 | 669739 | 681530 | 641899 | 10 |
vs Dorekori | 386770 | 363488 | 374979 | 374979 | 317234 | Candidate vs self | 590054 | 386770 | 374979 | 374979 | 363841 | 7 |
vs Tebulis | 374979 | 363488 | 374979 | 374979 | 134812 | 152342 | Candidate vs self | 351697 | 374979 | 374979 | 165516 | 5 |
vs Edelän | 695844 | 513967 | 362741 | 367827 | 60866 | 355626 | 390699 | Candidate vs self | 497166 | 513366 | 367417 | 5 |
vs Limbagge | 498347 | 514320 | 329378 | 169884 | 72657 | 367417 | 367417 | 245230 | Candidate vs self | 373521 | 367417 | 3 |
vs Tanthani | 623934 | 514320 | 268661 | 430583 | 60866 | 367417 | 367417 | 229030 | 368875 | Candidate vs self | 367417 | 3 |
vs Salmond | 543949 | 672209 | 374979 | 374979 | 100497 | 378555 | 576880 | 374979 | 374979 | 374979 | Candidate vs self | 9 |
WIN COUNT | 10 | 6 | 5 | 6 | 0 | 3 | 5 | 5 | 7 | 7 | 1 | |
MAX VOTES | 695844 | 672209 | 681530 | 681530 | 317234 | 425162 | 607584 | 681530 | 669739 | 681530 | 641899 | |
AVG VOTES | 538892.2 | 477489.6 | 351123.5 | 365277.9 | 108762.3 | 351588.7 | 438121 | 329844.1 | 411837.2 | 382544 | 327697.5 | |
RANK | 1 | 4 | 6 | 4 | 11 | 9 | 6 | 6 | 2 | 2 | 10 |
The votes are tallied up as follows: every candidate receives the votes of each group of voters who prefer them over their opponent, according to the preferences in the first table. Originally, I did this manually. I went through each time and summed up the number of votes. It got very exhausting, taking about two hours to carry out. And this was for only one situation where the votes fell in a certain way! I did it manually once again with slightly different vote counts, which took a few more hours. I started to think of writing a formula that could handle it all for me.
I poked at several things under query()
, lookup()
, and vlookup()
, none of which worked. I learned that none of them supported looking for matches in multiple cells across multiple rows and columns, or if they did, it was beyond my power to learn whether or not they did so tonight. Eventually, I got what I think might be the start of a workable formula. If, unfortunately, a very long one.
I started off by trying to change the value of cell B110 from a manual summation of the value I was looking for (the sum of all voters who prefer the candidate named in cells B2 and B95 over the candidate named in cell A110) to a formulaic one. The start of the formula is below.
=sumif($B$95:$B$105,if(match(B$95,$B$95:$B$105,0)<match(regexextract($A110,"vss([A-z|ä]+)"),$B$95:$B$105,0)=true,B$95,0),B106:L106)
It produced the following table. The only change from the second markdown table is that the cell right next to “vs Finwio” now only has the votes from the voters whose first preference is Melian:
CANDIDATE MATCHUPS (ORIGINAL) | Melian | Finwio | Kunlang | Lobbens | Grunxi | Dorekori | Tebulis | Edelän | Limbagge | Tanthani | Salmond | Win count against candidate |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs Melian | Candidate vs self | 367064 | 158093 | 118462 | 60866 | 355626 | 367417 | 46552 | 244049 | 118462 | 198447 | 0 |
vs Finwio | 146904 | Candidate vs self | 374979 | 228076 | 158093 | 378908 | 378908 | 228429 | 228076 | 228076 | 70187 | 4 |
vs Kunlang | 584303 | 367417 | Candidate vs self | 531480 | 60866 | 367417 | 367417 | 379655 | 413018 | 473735 | 367417 | 5 |
vs Lobbens | 623934 | 514320 | 210916 | Candidate vs self | 60866 | 367417 | 367417 | 374569 | 572512 | 311813 | 367417 | 4 |
vs Grunxi | 681530 | 584303 | 681530 | 681530 | Candidate vs self | 425162 | 607584 | 681530 | 669739 | 681530 | 641899 | 10 |
vs Dorekori | 386770 | 363488 | 374979 | 374979 | 317234 | Candidate vs self | 590054 | 386770 | 374979 | 374979 | 363841 | 7 |
vs Tebulis | 374979 | 363488 | 374979 | 374979 | 134812 | 152342 | Candidate vs self | 351697 | 374979 | 374979 | 165516 | 5 |
vs Edelän | 695844 | 513967 | 362741 | 367827 | 60866 | 355626 | 390699 | Candidate vs self | 497166 | 513366 | 367417 | 5 |
vs Limbagge | 498347 | 514320 | 329378 | 169884 | 72657 | 367417 | 367417 | 245230 | Candidate vs self | 373521 | 367417 | 3 |
vs Tanthani | 623934 | 514320 | 268661 | 430583 | 60866 | 367417 | 367417 | 229030 | 368875 | Candidate vs self | 367417 | 3 |
vs Salmond | 543949 | 672209 | 374979 | 374979 | 100497 | 378555 | 576880 | 374979 | 374979 | 374979 | Candidate vs self | 9 |
WIN COUNT | 10 | 6 | 5 | 6 | 0 | 3 | 5 | 5 | 7 | 7 | 1 | |
MAX VOTES | 695844 | 672209 | 681530 | 681530 | 317234 | 425162 | 607584 | 681530 | 669739 | 681530 | 641899 | |
AVG VOTES | 538892.2 | 477489.6 | 351123.5 | 365277.9 | 108762.3 | 351588.7 | 438121 | 329844.1 | 411837.2 | 382544 | 327697.5 | |
RANK | 1 | 4 | 6 | 4 | 11 | 9 | 6 | 6 | 2 | 2 | 10 |
The match formulas return the position of the cell in question, proxying for the preference of the voters who support the candidate named at the top of the column. If the candidate’s cell position is lower than that of their opponent, then the criterion for the sumif is the candidate’s name. Otherwise, it returns 0.
This only applies to one column out of eleven, of course. I’d need to copy and modify this eleven times for each of the eleven columns, representing the voters for each of the other ten candidates. In the end, the formula would be a
sum(sumif(the formula above),sumif(the formula above, but for column C), sumif (the formula above, for column D)
…for each column from B to L.
So…what I want is to find out if there exists a Google Sheets formula that can:
- find a way to put all of the columns and rows in the same array
- find and compare the position of two strings in multiple rows
- sum up all of the votes (here, the numbers in row 106) in each column where the string representing the candidate listed in the column has a lower row than their opponent
- provides the summed-up value in one cell
- performs the above in a more compact manner than summing up sumifs
And if so, I’d appreciate some help in building it. I can share a copy of the sheet I did all of the work on originally, if needed.
This is the sample Google Sheet I’ve made with the relevant data and my one-cell attempt at a formula change.
Sam Munroe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2