Skip to content

Commit

Permalink
restriction on imputed ranks
Browse files Browse the repository at this point in the history
  • Loading branch information
hanase committed Dec 8, 2023
1 parent d55f39d commit a66e1a9
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 8 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: vote
Type: Package
Title: Election Vote Counting
Version: 2.4-0.9001
Date: 2023-12-07
Version: 2.4-0.9002
Date: 2023-12-08
Author: Hana Sevcikova, Bernard Silverman, Adrian Raftery
Maintainer: Hana Sevcikova<[email protected]>
Description: Counting election votes and determining election results by different methods, including
Expand Down
21 changes: 16 additions & 5 deletions R/check_votes.R
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ impute.ranking <- function(votes, equal.ranking = FALSE, quiet = TRUE){
impvalues <- apply(votes.for.imp, 2, median, na.rm = TRUE)
# compute means as well in case we need to solve ordering of duplicates
impvalues.means <- apply(votes.for.imp, 2, mean, na.rm = TRUE)
skipped <- c()

# iterate over votes that need imputation
for(i in which(voters.with.conflict)){
Expand All @@ -153,19 +154,29 @@ impute.ranking <- function(votes, equal.ranking = FALSE, quiet = TRUE){
# iterate over ordered candidates
previous.imputed <- 0
for(ocan in can.order){
this.rank <- min(as.integer(round(ranks.to.impute[ocan])), max(votes[i, ], 0)+1)
this.rank <- as.integer(round(ranks.to.impute[ocan]))
if(!equal.ranking && this.rank == previous.imputed)
this.rank <- this.rank + 1 # avoid duplicates
if(this.rank > sum(votes[i, ] > 0) + 1){
# if the imputed rank is larger than the maximum preference plus one, set it to 0
votes[i, where.to.impute[ocan]] <- 0
skipped <- c(skipped, i)
next
}
ranks.to.shift <- !is.na(votes.for.imp[i, ]) & votes[i, ] >= this.rank &
! seq_len(ncol(votes)) %in% where.to.impute
votes[i, ranks.to.shift] <- votes[i, ranks.to.shift] + 1
votes[i, where.to.impute[ocan]] <- this.rank
previous.imputed <- this.rank
}
}
if(!quiet) cat("\nMedian ranks", paste(round(impvalues[cans], 1), collapse = ", "), "for candidate(s)",
paste(colnames(votes)[cans], collapse = ", "),
"was used for imputation into", sum(voters.with.conflict), "vote(s).\n")

if(!quiet) {
cat("\nMedian ranks used for imputation into", sum(voters.with.conflict), "vote(s) :\n")
print(data.frame(matrix(round(impvalues[cans], 1), byrow = TRUE, nrow = 1,
dimnames = list("rank", colnames(votes)[cans]))))
skipped <- unique(skipped)
if(length(skipped) > 0)
warning("Imputation skipped for votes ", paste(skipped, collapse = ", "), " due to non-missing preferences being too small.")
}
return(votes)
}
3 changes: 2 additions & 1 deletion man/stv.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ If equal ranking is not alowed (\code{equal.ranking = FALSE}), the argument \cod
The \code{correct.ranking} function does the above corrections for all records, regardless if they contain duplicates or not. Its argument \code{partial} determines if ballots are partially set to 0 (\code{TRUE}), or if it is complete re-ranking, as allowed when \code{equal.ranking = TRUE}. It can either be used by calling it explicitely, otherwise it is called by \code{stv} if \code{equal.ranking = TRUE} or \code{invalid.partial = TRUE}. The function is also called from within the \code{\link{condorcet}} function. The \code{remove.candidate} function removes the given candidate(s) and adjusts the ranked votes accordingly by calling the \code{correct.ranking} function.
The function allows to impute missing values. It can be used for example, if a voter has a conflict of interest with one or more candidates and not voting for them would unfairly decrease the chances of those candidates being elected. Preferences to be imputed should be set to \eqn{-1} and the argument \code{impute.missing} to \code{TRUE}. Each such preference is imputed using the median rank value over the remaining votes. When computing the median rank across the votes, any value of zero is replaced by the median of the ranks not used in the corresponding vote. For example, for a ballot \eqn{1,2,3,0,0,0}, the three zeros are replaced by the median of \eqn{4, 5, 6}, i.e. by \eqn{5}, which is then used to impute the missing median rank. This functionality is implemented in the \code{impute.ranking} function, which is called automatically from \code{stv} if \code{impute.missing = TRUE}. It can be used explicitely as well.
The function allows to impute missing values. It can be used for example, if a voter has a conflict of interest with one or more candidates and not voting for them would unfairly decrease the chances of those candidates being elected. Preferences to be imputed should be set to \eqn{-1} and the argument \code{impute.missing} to \code{TRUE}. Each such preference is imputed using the median rank value over the remaining votes. When computing the median rank across the votes, any value of zero is replaced by the median of the ranks not used in the corresponding vote. For example, for a ballot \eqn{1,2,3,0,0,0}, the three zeros are replaced by the median of \eqn{4, 5, 6}, i.e. by \eqn{5}, which is then used to compute the missing median rank. If the final imputed rank is larger than the number of non-zero preferences (e.g. if in a ballot \eqn{1,2,0,-1,0} the imputed value for the fourth candidate would be larger than 3), the preference is set to zero and a warning is issued.
The described functionality is implemented in the \code{impute.ranking} function, which is called automatically from \code{stv} if \code{impute.missing = TRUE}. It can be used explicitely as well.
By default, ties in the STV algorithm are resolved using the forwards tie-breaking method, see Newland and Briton (Section 5.2.5). Argument \code{ties} can be set to \dQuote{b} in order to use the backwards tie-breaking method, see O'Neill (2004). In addition, both methods are complemented by the following \dQuote{ordered} method: Prior to the STV election candidates are ordered by the number of 1st preferences. Equal ranks are resolved by moving to the number of 2nd preferences, then 3rd and so on. Remaining ties are broken by random draws. Such complete ordering is used to break any tie that cannot be resolved by the forwards or backwards method. If there is at least one tie during the processing, the output contains a row indicating in which count a tie-break happened (see the \code{ties} element in the Value section for an explanation of the symbols).

Expand Down

0 comments on commit a66e1a9

Please sign in to comment.