Categories
Election Data Analysis Election Forensics Election Integrity programming technical

VHL, RVL and DAL metrics for VA 2021 and (2020) General Elections

As I now have available the Registered Voter List (RVL), the Voter History List (VHL) and the completed Daily Absentee List (DAL) files for the 2020 and 2021 VA November General elections, I did some basic metrics computations on these files for those that are interested. The Voter History and Registered Voter List files used to generate these results were downloaded from VA Dept of Elections on 2021-12-11. The 2021 DAL file used was downloaded 2021-12-05. The 2020 DAL file was downloaded 2020-11-09.

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Basic Voter History and Registered Voter List Metrics
nInPDayOf2020 = 1638026 
nAbs2020 = 2734048 
nInPAbsOf2020 =  657 

nInPDayOf2021 = 1721868 
nAbs2021 = 1188842 
nInPAbsOf2021 = 0 

nUniqueVHIDs = 4769508 
nUniqueRVLIDs = 5956464 
nIntersectUVVHwURVL = 4769508 

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ages of the registered voters at the time of the election from RVL
regv_over100_On2021Elect = 2736 
regv_regv_lessThan18_On2021Elect = 397 
regv_over100_On2020Elect = 1774 
regv_lessThan18_On2020Elect = 43939 
regv_lessThan17_On2020Elect = 391

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ages of the registered voters at the time of the election from VHL
vh_over100_On2021Elect = 514 
vh_lessThan18_On2021Elect = 0 
vh_over100_On2020Elect = 558 
vh_lessThan18_On2020Elect = 1 
vh_lessThan17_On2020Elect = 0

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Do some basic indexing of different DAL status categories and combinations
nApprovedAndIssued2021 = 58151 
nApprovedAndMarked2021 = 78278 
nApprovedAndOnMachine2021 = 861470 
nApprovedAndPreProcessed2021 = 254374 
nApprovedAndFWAB2021 = 52 
nApprovedAndCountable2021 = 1194174 

nApprovedAndIssued2020 = 106037 
nApprovedAndMarked2020 = 348705 
nApprovedAndOnMachine2020 = 1796973
nApprovedAndPreProcessed2020 = 670765
nApprovedAndFWAB2020 = 1351
nApprovedAndCountable2020 = 2817794

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many countable entries in the 2021 dal are not contained in the voter
% registraion file for 2021
phantomDALVoters2021 = 0

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many countable entries in the 2020 dal are not contained in the voter
% registraion file for 2021
phantomDALVoters2020 = 48721

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many approved but not counted entries in the 2020 dal are not
% contained in the voter registraion file for 2021?  
phantomDALBallots2020 = 3671

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were issued but not counted or spoiled AND the
% person is marked as having voted in person on election day
% For 2020:
numUnspoiled2020 = 106037
numUnspoiledAndInPDayOf2020 = 35806

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were issued but not counted or spoiled AND the
% person is marked as having voted in person on election day
% For 2021:
numUnspoiled2021 = 58151
numUnspoiledAndInPDayOf2021 = 4632

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were approved and counted AND the
% person is marked as having voted IN PERSON on election day. (Should be 0)
% For 2020:
numCountedAbs2020 = 2817794
numCountedAbs2020AndInPDayOf2020 = 245

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were approved and counted AND the
% person is marked as having voted IN PERSON on election day. (Should be 0)
% For 2021:
numCountedAbs2021 = 1194174
numCountedAbs2021AndInPDayOf2021 = 14

The MATLAB program listing for generating these metrics is below. I have left off the parsing routines that parse the various csv input files into MATLAB Table objects. Text highlighted in BOLD is the computed metric results as listed above.

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Basic Voter History and Registered Voter List Metrics
inPDayOf2020 = VAVoteHistory.ELECTION_NAME=='2020 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2020 & ...
    VAVoteHistory.ABSENTEE == 'False';
abs2020 = VAVoteHistory.ELECTION_NAME=='2020 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2020 & ...
    VAVoteHistory.ABSENTEE == 'True';
inPAbsOf2020 = VAVoteHistory.ELECTION_NAME=='2020 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2020 & ...
    VAVoteHistory.ABSENTEE == 'True' & VAVoteHistory.VOTE_IN_PERSON=='True';
nInPDayOf2020 = sum(inPDayOf2020)
nAbs2020 = sum(abs2020)
nInPAbsOf2020 = sum(inPAbsOf2020)
inPDayOf2021 = VAVoteHistory.ELECTION_NAME=='2021 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2021 & ...
    VAVoteHistory.ABSENTEE == 'False';
abs2021 = VAVoteHistory.ELECTION_NAME=='2021 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2021 & ...
    VAVoteHistory.ABSENTEE == 'True';
inPAbsOf2021 = VAVoteHistory.ELECTION_NAME=='2021 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2021 & ...
    VAVoteHistory.ABSENTEE == 'True' & VAVoteHistory.VOTE_IN_PERSON=='True';
nInPDayOf2021 = sum(inPDayOf2021)
nAbs2021 = sum(abs2021)
nInPAbsOf2021 = sum(inPAbsOf2021)
uvhid = unique(VAVoteHistory.IDENTIFICATION_NUMBER);
urvlid = unique(RegisteredVoterList.IDENTIFICATION_NUMBER);
nUniqueVHIDs = numel(uvhid)
nUniqueRVLIDs = numel(urvlid)
intersectUVVHwURVL = intersect(uvhid,urvlid);
nIntersectUVVHwURVL = numel(intersectUVVHwURVL)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ages of the registered voters at the time of the election from RVL
dob = datenum(RegisteredVoterList.DOB);
ageOn2021Elect = (datenum("11/03/2021") - dob) / 365.25;
ageOn2020Elect = (datenum("11/04/2020") - dob) / 365.25;

regv_over100_On2021Elect = sum(ageOn2021Elect > 100)
regv_lessThan18_On2021Elect = sum(ageOn2021Elect < 18)
regv_over100_On2020Elect = sum(ageOn2020Elect > 100)
regv_lessThan18_On2020Elect = sum(ageOn2020Elect < 18)
regv_lessThan17_On2020Elect = sum(ageOn2020Elect < 17)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ages of the registered voters at the time of the election from VHL
vh2021 = VAVoteHistory.ELECTION_NAME=='2021 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2021;
vh2020 = VAVoteHistory.ELECTION_NAME=='2020 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2020;
dob_vh = datenum(VAVoteHistory.DOB);
ageOn2021Elect_vh = (datenum("11/03/2021") - dob_vh) / 365.25;
ageOn2020Elect_vh = (datenum("11/04/2020") - dob_vh) / 365.25;

vh_over100_On2021Elect = sum(ageOn2021Elect_vh(vh2021) > 100)
vh_lessThan18_On2021Elect = sum(ageOn2021Elect_vh(vh2021) < 18)
vh_over100_On2020Elect = sum(ageOn2020Elect_vh(vh2020) > 100)
vh_lessThan18_On2020Elect = sum(ageOn2020Elect_vh(vh2020) < 18)
vh_lessThan17_On2020Elect = sum(ageOn2020Elect_vh(vh2020) < 17)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Do some basic indexing of different DAL status categories and combinations
aiv2021 = dal2021.APP_STATUS == 'Approved' & dal2021.BALLOT_STATUS == 'Issued';
amv2021 = dal2021.APP_STATUS == 'Approved' & dal2021.BALLOT_STATUS == 'Marked';
aomv2021 = dal2021.APP_STATUS == 'Approved' & dal2021.BALLOT_STATUS == 'On Machine';
appv2021 = dal2021.APP_STATUS == 'Approved' & dal2021.BALLOT_STATUS == 'Pre-Processed';
afwv2021 = dal2021.APP_STATUS == 'Approved' & dal2021.BALLOT_STATUS == 'FWAB';
appmv2021 = amv2021 | aomv2021 | appv2021 | afwv2021; % Approved and Countable

aiv2020 = dal2020.APP_STATUS == 'Approved' & dal2020.BALLOT_STATUS == 'Issued';
amv2020 = dal2020.APP_STATUS == 'Approved' & dal2020.BALLOT_STATUS == 'Marked';
aomv2020 = dal2020.APP_STATUS == 'Approved' & dal2020.BALLOT_STATUS == 'On Machine';
appv2020 = dal2020.APP_STATUS == 'Approved' & dal2020.BALLOT_STATUS == 'Pre-Processed';
afwv2020 = dal2020.APP_STATUS == 'Approved' & dal2020.BALLOT_STATUS == 'FWAB';
appmv2020 = amv2020 | aomv2020 | appv2020 | afwv2020; % Approved and Countable

nApprovedAndIssued2021 = sum (aiv2021)
nApprovedAndMarked2021 = sum (amv2021)
nApprovedAndOnMachine2021 = sum (aomv2021)
nApprovedAndPreProcessed2021 = sum (appv2021)
nApprovedAndFWAB2021 = sum (afwv2021)
nApprovedAndCountable2021 = sum (appmv2021)

nApprovedAndIssued2020 = sum (aiv2020)
nApprovedAndMarked2020 = sum (amv2020)
nApprovedAndOnMachine2020 = sum (aomv2020)
nApprovedAndPreProcessed2020 = sum (appv2020)
nApprovedAndFWAB2020 = sum (afwv2020)
nApprovedAndCountable2020 = sum (appmv2020)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many countable entries in the 2021 dal are not contained in the voter
% registraion file for 2021?
ua = unique(string(dal2021.identification_number(appmv2021)));
ub = unique(string(RegisteredVoterList.IDENTIFICATION_NUMBER));
[uc,ia,ib] = intersect(ua,ub);
phantomDALPct2021 = numel(uc) / numel(ua) * 100
phantomDALVoters2021 = numel(ua) - numel(uc)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many countable entries in the 2020 dal are not contained in the voter
% registraion file for 2021? 
[ua2020,ia,ic] = unique(string(dal2020.identification_number(appmv2020)));
ub2020 = unique(string(RegisteredVoterList.IDENTIFICATION_NUMBER));
[uc2020] = intersect(ua2020,ub2020);
phantomDALPct2020 = numel(uc2020) / numel(ua2020) * 100
phantomDALVoters2020 = numel(ua2020) - numel(uc2020)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many approved but not counted entries in the 2020 dal are not
% contained in the voter registraion file for 2021?  
[ua2020,ia,ic] = unique(string(dal2020.identification_number(aiv2020)));
ub2020 = unique(string(RegisteredVoterList.IDENTIFICATION_NUMBER));
[uc2020] = intersect(ua2020,ub2020);
phantomDALBallotsPct2020 = numel(uc2020) / numel(ua2020) * 100
phantomDALBallots2020 = numel(ua2020) - numel(uc2020)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were issued but not counted or spoiled AND the
% person is marked as having voted in person on election day
% For 2020:
unspoiled2020 = dal2020.identification_number(aiv2020);
ngIPDOidx = VAVoteHistory.ELECTION_NAME=='2020 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2020 & ...
    VAVoteHistory.ABSENTEE == 'False';
novGenInPersonDayOf2020 = VAVoteHistory.IDENTIFICATION_NUMBER(ngIPDOidx);
ua2020 = unique(unspoiled2020);
ub2020 = unique(novGenInPersonDayOf2020);
uc2020 = intersect(ua2020,ub2020);
numUnspoiled2020 = numel(unspoiled2020)
numUnspoiledAndInPDayOf2020 = numel(uc2020)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were issued but not counted or spoiled AND the
% person is marked as having voted in person on election day
% For 2021:
unspoiled2021 = dal2021.identification_number(aiv2021);
ngIPDOidx = VAVoteHistory.ELECTION_NAME=='2021 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2021 & ...
    VAVoteHistory.ABSENTEE == 'False';
novGenInPersonDayOf2021 = VAVoteHistory.IDENTIFICATION_NUMBER(ngIPDOidx);
ua2021 = unique(unspoiled2021);
ub2021 = unique(novGenInPersonDayOf2021);
uc2021 = intersect(ua2021,ub2021);
numUnspoiled2021 = numel(unspoiled2021)
numUnspoiledAndInPDayOf2021 = numel(uc2021)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were approved and counted AND the
% person is marked as having voted IN PERSON on election day. (Should be 0)
% For 2020:
countedAbs2020 = dal2020.identification_number(appmv2020);
ngIPDOidx = VAVoteHistory.ELECTION_NAME=='2020 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2020 & ...
    VAVoteHistory.ABSENTEE == 'False';
novGenInPersonDayOf2020 = VAVoteHistory.IDENTIFICATION_NUMBER(ngIPDOidx);
ua2020 = unique(countedAbs2020);
ub2020 = unique(novGenInPersonDayOf2020);
uc2020 = intersect(ua2020,ub2020);
numCountedAbs2020 = numel(countedAbs2020)
numCountedAbs2020AndInPDayOf2020 = numel(uc2020)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How many absentee ballots were approved and counted AND the
% person is marked as having voted IN PERSON on election day. (Should be 0)
% For 2021:
countedAbs2021 = dal2021.identification_number(appmv2021);
ngIPDOidx = VAVoteHistory.ELECTION_NAME=='2021 November General' & ...
    VAVoteHistory.ELECTION_YEAR==2021 & ...
    VAVoteHistory.ABSENTEE == 'False';
novGenInPersonDayOf2021 = VAVoteHistory.IDENTIFICATION_NUMBER(ngIPDOidx);
ua2021 = unique(countedAbs2021);
ub2021 = unique(novGenInPersonDayOf2021);
uc2021 = intersect(ua2021,ub2021);
numCountedAbs2021 = numel(countedAbs2021)
numCountedAbs2021AndInPDayOf2021 = numel(uc2021)