Reputation: 187
I am currently working on a small project that involves analysing ballot papers and determining the winning candidate based on the number of votes they receive. The voting system used is very unusual. For example, if there are four candidates the vote could look like this: 3241 (3 points for the first candidate, 2 points for the second candidate etc). To determine the winner I have to add up all of the votes for each candidate. For example, if the 3 ballots were [1342, 3241, 3214] the amount of points for the first candidate would be 1+3+3 = 7 (Lower the better). Declaring the winner if there is no draw is very simple. It begins to get quite difficult when there is a tie for points. For the example above, the final score would be [7,7,9,7]. To declare the winner if there is a tie I need to look at the preference order of the votes (basically check how many 1's each candidate got, how many 2's each candidate got etc) and store them in a list which look something like this:
[[1, 0, 1, 1], [0, 2, 0, 1], [2, 1, 0, 0], [0, 0, 2, 1]]
I have managed to create the list above. However, I am now having trouble declaring the winner, in this situation the winner should be the 4th candidate. As the they are tied for first preference votes, but they have the most second preference votes out of the candidates who were initially tied.
Code:
for lists in drawList: # drawList is list of zeros
for num in lists:
if num == 0:
lists.remove(0)
maximum = max(lists)
count = lists.count(maximum)
if count == 1:
for i, num in enumerate(lists):
if num == count:
winner = nameList[i]
print(i)
break
I have tried the code above however it seems to give back a reversed result, declaring the loser as the winner. I am just wondering if there is a good way to declare a winner using the list above, comparing the number of votes each candidate got in each section. Thanks in advance.
Upvotes: 0
Views: 102
Reputation: 815
Not the best code, need to be cleaned... But you can first select the candidates with the lowest votes. After that select apply the cumsum. And check the very first row where there is no tie (different number of votes). the last line returns the candidate.
import pandas as pd
import numpy as np
df = pd.DataFrame(ls, columns=[f'candidate_{x}' for x in range(len(ls) + 1)])
df_t = df.T.copy()
df_filtered = df_t[df_t.sum(axis=1) == min(df_t.sum(axis=1))].T
candidates_ls = []
for candidate in df_filtered.columns:
aux = df_filtered[candidate]
candidates_ls.append(aux.sort_values().cumsum().values)
cumsum = pd.DataFrame(candidates_ls).T
cumsum.columns = df_filtered.columns
cumsum['min'] = cumsum.apply(lambda x: np.where(x == x.min())[0], 1)
cumsum['unique'] = cumsum['min'].apply(lambda x: len(x) == 1)
df_filtered.columns[cumsum[cumsum['unique']].iloc[0]['min'][0]]
Upvotes: 1
Reputation: 566
You can do this via recursion:
lst = [[1, 0, 1, 1], [0, 2, 0, 1], [2, 1, 0, 0], [2, 0, 2, 1]]
def get_highest(lst, depth=0):
curr_max = -1
curr_max_elements = []
if(len(lst) < depth):
print("Error.")
if(len(lst) == 1):
return lst
for i in range(len(lst)):
if lst[i][depth] > curr_max:
curr_max = lst[i][depth]
curr_max_elements = [lst[i]]
elif lst[i][depth] == curr_max:
curr_max_elements.append([lst[i]])
return get_highest(curr_max_elements, depth+1)
print(get_highest([[1, 0, 1, 1], [0, 2, 0, 1], [2, 1, 0, 0], [0, 0, 2, 1]]))
>> [[2, 1, 0, 0]]
Every call you just keep the largest elements, then check one element further etc etc
Upvotes: 1