Adding onto the work I’ve already done looking at the VA Daily Absentee List I wanted to compute the rejection rate for absentee ballots and some other basic statistics just from the Daily Absentee Ballot List (DAL) produced by VA Dept of Elections. (https://www.elections.virginia.gov/candidatepac-info/client-services/)
Keep in mind I’ve already been able to show:
- There were 166 Absentee Ballot Applications that were received and accepted AFTER the corresponding ballot was received or accepted (here).
- There is a discrepancy in the number of “excess” absentee votes counted vs. the total accepted registrations from the Daily Absentee List (here).
- The 2020 VA election fingerprints, as well as other states, have significant structural irregularities and indications of vote manipulation (here).
- The VA election fingerprints show a trend of increasing irregularity starting with 2008, 2012, 2016 and now 2020 (here).
Basic Info:
There are 3335335 entries, with 36 columns in the Daily Absentee List.
The column headings are: ELECTION_NAME, LOCALITY_CODE, LOCALITY_NAME, PRECINCT_CODE, PRECINCT_NAME, LAST_NAME, FIRST_NAME, MIDDLE_NAME, SUFFIX, ADDRESS_LINE_1, ADDRESS_LINE_2, ADDRESS_LINE_3, CITY, STATE, ZIP, COUNTRY, INTERNATIONAL, EMAIL_ADDRESS, FAX, VOTER_TYPE, ONGOING, APP_RECIEPT_DATE, APP_STATUS, BALLOT_RECEIPT_DATE, BALLOT_STATUS, identification_number, PROTECTED, CONG_CODE_VALUE, STSENATE_CODE_VALUE, STHOUSE_CODE_VALUE, AB_ADDRESS_LINE_1, AB_ADDRESS_LINE_2, AB_ADDRESS_LINE_3, AB_CITY, AB_STATE, AB_ZIP
Computing the Absentee Ballot Rejection Rate:
So (in MATLAB), with the full list directly imported into the ‘DailyAbsenteeList’ table variable:
% Lets see if we can teas out the rejection rate for
% absentee ballots
>> ineligable = DailyAbsenteeList.APP_STATUS == "Denied/Not Eligible";
>> incomplete = DailyAbsenteeList.APP_STATUS == "Denied/Incomplete";
>> rejectionRate = 100 * mean(ineligable | incomplete)
>> ans = 0.0425
RESULT: The absentee ballot rejection rate was an exceptionally low 0.0425%
Finding the Counted ballots:
As we did in the “excess vote” computation, we need to find the indices into the list of all of the ballots that were counted, meaning their BALLOT_STATUS is in one of the following states: {‘On Machine’, ‘Marked’, ‘Pre-Processed’, ‘FWAB’}. So the ‘idxv’ variable below is a boolean flag indicating that the BALLOT_STATUS of each entry in the list is in a countable state.
% For each entry in the Daily Absentee List, test if
% BALLOT_STATUS is in a valid state
>> idxv = DailyAbsenteeList.BALLOT_STATUS=='Marked' | ...
DailyAbsenteeList.BALLOT_STATUS=='Pre-Processed' | ...
DailyAbsenteeList.BALLOT_STATUS=='On Machine' | ...
DailyAbsenteeList.BALLOT_STATUS=='FWAB';
Now one would think that if a ballot has been marked into one of those BALLOT_STATUS categories, then that ballot application should have been ‘Approved’, right? Well lets double check that shall we:
% For each entry in the Daily Absentee List, test if
% BALLOT_STATUS is in a valid state AND APP_STATUS is set to
% 'Approved'. (One would think these would match.)
>> idxav = (DailyAbsenteeList.BALLOT_STATUS=='Marked' | ...
DailyAbsenteeList.BALLOT_STATUS=='Pre-Processed' | ...
DailyAbsenteeList.BALLOT_STATUS=='On Machine' | ...
DailyAbsenteeList.BALLOT_STATUS=='FWAB') & ...
DailyAbsenteeList.APP_STATUS=='Approved';
We can check for mismatches by counting the number of flags that are not equal between ‘idxv’ and ‘idxav’.
% How many absentee ballots have their BALLOT_STATUS set to
% a valid (i.e. "countable") state, but are not marked as
% 'Approved'
>> numUnapprovedButCountableVotes = sum(idxv)-sum(idxav)
>> ans = 1437
RESULT: There are 1437 entries that have BALLOT_STATUS set to a valid state, but don’t have an approved absentee ballot application
Well … this begs some follow up questions…
Q1: Of the ballots that have been set to a valid BALLOT_STATUS state but were not set to ‘Approved’, what is the breakdown by APP_STATUS?
>> cancelled = sum(DailyAbsenteeList.APP_STATUS=='Cancelled or Duplicate' & (idxv~=idxav))
>> deniedInc = sum(DailyAbsenteeList.APP_STATUS=='Denied/Incomplete' & (idxv~=idxav))
>> deniedIne = sum(DailyAbsenteeList.APP_STATUS=='Denied/Not Eligible' & (idxv~=idxav))
>> issued = sum(DailyAbsenteeList.APP_STATUS=='Issued' & (idxv~=idxav))
>> onHold = sum(DailyAbsenteeList.APP_STATUS=='On Hold' & (idxv~=idxav))
>> pending = sum(DailyAbsenteeList.APP_STATUS=='Pending Approval' & (idxv~=idxav))
>> provisional = sum(DailyAbsenteeList.APP_STATUS=='Provisional' & (idxv~=idxav))
RESULTS: Of the 1437 ballots that were in a countable state but not marked as having APP_STATUS=’Accepted’, their APP_STATUS was:
cancelled = 444
deniedInc = 568
deniedIne = 4
issued = 28
onHold = 101
pending = 288
provisional = 4
Q2: Of the ballots that have been set to a valid BALLOT_STATUS state but were not set to ‘Approved’, what is the breakdown by BALLOT_STATUS?
>> unapproved_mailIn = sum(DailyAbsenteeList.BALLOT_STATUS=='Marked' & ...
DailyAbsenteeList.APP_STATUS~='Approved')
>> unapproved_preProcessed = sum(DailyAbsenteeList.BALLOT_STATUS=='Pre-Processed' & ...
DailyAbsenteeList.APP_STATUS~='Approved')
>> unapproved_earlyInPerson = sum(DailyAbsenteeList.BALLOT_STATUS=='On Machine' & ...
DailyAbsenteeList.APP_STATUS~='Approved')
>> unapproved_FWAB = sum(DailyAbsenteeList.BALLOT_STATUS=='FWAB' & ...
DailyAbsenteeList.APP_STATUS~='Approved')
RESULTS: Of the 1437 ballots that were in a countable state but not marked as having APP_STATUS=’Accepted’, their BALLOT_STATUS was:
unapproved_MailIn (‘Marked’) = 512
unapproved_preProcessed (‘Pre-Processed’) = 578
unapproved_earlyInPerson (‘On Machine’) = 347
unapproved_FWAB (‘FWAB’) = 0
Checking for duplicate identities:
Another check we can do is try to determine the amount of duplicated voters that have been accepted.
% What about the possibility of the same person being marked
% with multiple ballots? We will now go through
% the'Accepted' and countable ballots and
% look for duplicate names and address information.
>> idxvs = find(idxav);
>> fnames = cellstr(DailyAbsenteeList.FIRST_NAME(idxvs));
>> lnames = cellstr(DailyAbsenteeList.LAST_NAME(idxvs));
>> mnames = cellstr(DailyAbsenteeList.MIDDLE_NAME(idxvs));
>> sffx = cellstr(DailyAbsenteeList.SUFFIX(idxvs));
>> addy1 = cellstr(DailyAbsenteeList.ADDRESS_LINE_1(idxvs));
>> addy2 = cellstr(num2str(DailyAbsenteeList.ADDRESS_LINE_2(idxvs)));
>> addy3 = cellstr(num2str(DailyAbsenteeList.ADDRESS_LINE_3(idxvs)));
>> zips = cellstr(num2str(DailyAbsenteeList.ZIP(idxvs)));
>> addy2 = strrep(strrep(addy2,'NaN',''),' ','');
>> addy3 = strrep(strrep(addy3,'NaN',''),' ','');
>> zips = strrep(strrep(zips,'NaN',''),' ','');
>> namesAndAddys = join([fnames, mnames, lnames, sffx, addy1, addy2, addy3, zips]);
>> [unames,unr,uni] = unique(namesAndAddys);
>> duplicateVotes = numel(namesAndAddys) - numel(unames)
>> ans = 166