Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@osteele
Last active September 26, 2017 16:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save osteele/0caa190ef8070cbe67754460e9f2fa49 to your computer and use it in GitHub Desktop.
Save osteele/0caa190ef8070cbe67754460e9f2fa49 to your computer and use it in GitHub Desktop.
Count the votes in a Liquid Democracy Google Sheet
import pandas as pd
spreadsheet_key = '' # from the Google sheets Publish URL
spreadsheet_range = '' # e.g. B6:E15
url = 'https://docs.google.com/spreadsheets/d/e/{}/pub?gid=0&single=true&output=csv'.format(spreadsheet_key)
if spreadsheet_range:
url += '&range=' + spreadsheet_range
# TODO read this from the doc
df = pd.read_csv(url, names=['Voter', 'Vote', 'Delegate', 'Position'], index_col=0)
dups = df.index.get_duplicates()
assert not dups, "{} voted twice".format(', '.join(dups))
def fixed_point(f, df):
"""Find the fixed point of a DataFrame function."""
while True:
df0, df = df, f(df)
if df.equals(df0):
return df
def follow_delegates(df):
"""Return a new DataFrame with empty votes updated from delegates' votes."""
# Each voter's delegate, or themself if they didn't choose a delegate
delegates = df['Delegate'].fillna(df.index.to_series())
delegate_vote = delegates.apply(dict(df['Vote']).__getitem__)
return df.assign(Vote=df['Vote'].fillna(delegate_vote))
# Fill in missing votes by delegates' votes, or delegates' delegates' votes, etc.
df = fixed_point(follow_delegates, df)
# Warn (don't error) on unresolved votes.
# FIXME "voters" who entered neither a vote nor delegate should be reported separately
nas = df['Vote'].isnull().sum()
if nas:
print("{} delegated votes did not resolve".format(nas))
counts = df['Vote'].value_counts()
print('Totals:\n{}\n'.format(counts.to_string()))
winners = counts[counts == counts[counts.idxmax()]].index
if len(winners) > 1:
print('Winners (tie):', ', '.join(winners.index))
else:
print('Winner:', winners[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment