rlauxe

Redaction notes for Corla 2020 election

last changed 9/23/2026

See Corla2020notes for description of the cvr files.

Compare CVR files (from votedatabase) with manifest (auditcenter)

Style and Aggregated votes, no Ids

This is called “row redaction”: the entire row is redacted, the aggregations are given, in this case aggregated by style.

Individual cards with Style and IDs, no vote counts

This is called “column redaction”: the ids are retained and the votes are redacted.

No Redactions, but can infer from reported votes and manifest

A form of “row redaction”: the entire row is redacted, no aggregation. Derive the missing card ids and count from the manifest. Derive the vote aggregation from the “voteDifference”.

  1. Examine the manifest for entries that dont appear in the CVRs; count = missing
  2. Subtract CVR tabulations from reported vote totals = “voteDifference”.
  3. minCardsForVote = minimum ncards needed for voteDifference

Arapahoe has 100 missing cards, but vote difference (reported - cvrs) needs 115. The reported population agrees with the manifest, but the reported votes are inconsistent in 3 contests. One thing to do is to increase the population and the redacted pool by 115. This leaves the reported vote intact. In a real election, we could resolve the discrepency. In our simulation, it means that the simulated ballots will be short of the reported votes.

Run Redaction program on 2020 County CVR files as is

Does anonymize_cvr.py think that redactions are needed? Standard paremenets are minBallots = 10, contest_balancing = true.

needs redaction

Summary

totalManifest = 4104185
   totalNcvrs = 4100064
 totalMissing =    4121

redactedCvrs = 3171
totalNgroups = 42
ncounties with missing > 0 = 18

“Trust the manifest” CVR redaction reading algorithm

  1. Discard CVRs that dont appear in the manifest.
  2. Create a redacted pool for Manifest entries that dont appear in the CVRs. Use voteDifference for the pool subtotals.
  3. Verify that when redacted rows are present in the CVRs, they are also present in the manifest.
  4. Make a single redacted pool for each contest (onepool variant); ignore style information for now. The pool is a OneAudit pool with subtotal = voteDifference. Use county reported vote total.
  5. When doing the phantom variant, I think you have to use the cvr vote totals (not reported), leave out the redacted cards, and add nphantoms = nredactions. Use cvr tab for the county reported vote total.
  6. Make the state total from the county totals. Note that the phantom variant changes the state vote totals, since you are using cvr total without redactions.

In summary:

Using this algorithm on the 2020 General election, the following table shows which counties had redactions.

The column “missing” is the number of cards in each county’s redacted pool:

county phantoms population manifestCount cvrUnredacted cvrRedacted missing manifestNoCvr minCardsForVote cvrInManifest cvrNoManifest nredacted
Adams 0 239425 239425 239409 0 16 16 16 239409 0 0
Alamosa 0 7923 7923 7923 0 0 0 0 7923 0 0
Arapahoe 0 354347 354347 354247 0 100 100 115 354247 0 84
Archuleta 0 9404 9404 9404 0 0 0 0 9404 0 0
Bent 0 2295 2295 2295 0 0 0 0 2295 0 0
Boulder 0 208445 208445 205796 0 2649 2649 2628 205796 0 0
Broomfield 0 47103 47103 47103 0 0 0 0 47103 0 0
Chaffee 0 13862 13862 13862 0 0 0 0 13862 0 0
Cheyenne 0 1146 1146 1146 0 0 0 0 1146 0 0
Clear Creek 0 6608 6608 6608 0 0 0 0 6608 0 0
Conejos 0 4404 4404 4404 0 0 0 0 4404 0 0
Costilla 0 2139 2139 2139 0 0 0 0 2139 0 0
Crowley 0 1769 1769 1769 0 0 0 0 1769 0 0
Custer 0 3670 3670 3670 0 0 0 0 3670 0 0
Delta 0 19553 19553 19553 0 0 0 0 19553 0 0
Denver 0 1181464 1181464 1181464 0 0 0 0 1181464 0 34
Dolores 0 1500 1500 1500 0 0 0 0 1500 0 0
Douglas 0 234272 234272 234216 56 0 56 56 234216 0 0
Eagle 0 58589 58589 58571 20 -2 20 9 58569 2 0
El Paso 0 382583 382583 383160 44 -621 159 8 382424 736 0
Elbert 0 19150 19150 19150 0 0 0 0 19150 0 0
Fremont 0 26289 26289 26289 0 0 0 0 26289 0 0
Garfield 0 31245 31245 30544 0 701 701 690 30544 0 0
Gilpin 0 4239 4239 4240 0 -1 0 0 4239 1 0
Grand 0 10483 10483 10483 0 0 0 0 10483 0 0
Hinsdale 0 640 640 640 0 0 0 0 640 0 0
Huerfano 0 4459 4459 4459 0 0 0 0 4459 0 0
Jackson 0 889 889 886 0 3 3 3 886 0 0
Jefferson 0 381834 381834 381793 47 -6 47 32 381787 6 0
Kiowa 0 909 909 909 0 0 0 0 909 0 0
Kit Carson 0 3892 3892 3893 0 -1 0 0 3892 1 0
La Plata 0 35995 35995 35995 0 0 0 0 35995 0 20
Lake 0 4010 4010 4010 0 0 0 0 4010 0 0
Larimer 0 226896 226896 226844 57 -5 57 52 226839 5 40
Lincoln 0 2665 2665 2665 0 0 0 0 2665 0 0
Logan 0 10685 10685 10664 21 0 21 21 10664 0 0
Mesa 0 91506 91506 91506 0 0 0 0 91506 0 56
Mineral 0 767 767 767 0 0 0 0 767 0 0
Moffat 0 7074 7074 7074 0 0 0 0 7074 0 0
Montezuma 0 15631 15631 15631 0 0 0 0 15631 0 0
Montrose 0 25159 25159 25159 0 0 0 0 25159 0 0
Morgan 0 13860 13860 13855 5 0 5 5 13855 0 0
Otero 0 9704 9704 9704 0 0 0 0 9704 0 0
Ouray 0 4050 4050 4050 0 0 0 0 4050 0 0
Park 0 12406 12406 12406 0 0 0 0 12406 0 0
Phillips 0 2561 2561 2561 0 0 0 0 2561 0 0
Pitkin 0 12089 12089 12063 26 0 26 23 12063 0 0
Prowers 0 5601 5601 5601 0 0 0 0 5601 0 0
Pueblo 0 89155 89155 89108 47 0 47 46 89108 0 0
Rio Blanco 0 3709 3709 3705 4 0 4 4 3705 0 0
Rio Grande 0 6451 6451 6451 0 0 0 0 6451 0 0
Routt 0 33008 33008 33008 0 0 0 0 33008 0 18
Saguache 0 6821 6821 6821 0 0 0 0 6821 0 31
San Miguel 0 5189 5189 5190 0 -1 0 0 5189 1 0
Sedgwick 0 1496 1496 1496 0 0 0 0 1496 0 17
Summit 0 18943 18943 18788 169 -14 169 154 18774 14 0
Teller 91 17178 17087 17087 0 91 0 91 17087 0 0
Washington 0 3028 3028 3028 0 0 0 0 3028 0 0
Weld 0 169080 169080 169061 41 -22 41 27 169039 22 0
Yuma 0 5029 5029 5029 0 0 0 0 5029 0 0

where

field example description
county Larimer county name
phantoms 0 population - manifestCount
population 226896 county population from round.ballotCardCount
manifestCount 226896 number of entries in the manifest
cvrUnredacted 226844 count of unredacted Cvrs
cvrRedacted 57 count of redacted Cvrs
missing -5 manifestCount - (cvrUnredacted + cvrRedacted)
manifestNoCvr 57 count of Manifest entries that dont match cvrs
minCardsForVote 52 minimum cards needed for missing votes
cvrInManifest 226839 count of Cvrs that match entries in the Manifest
cvrNoManifest 5 count of Cvrs that dont match entries in the Manifest
nredacted 40 number of redacted rows added by Anonymizer

Compare redaction variants

(Skipping “styles” variant for now, as none of the existing cvr files can support it).

  ncontests nredactions ncards npools phantoms onePool unredacted
Corla2020 562 4121 4104185 18 19721 (561) 17182 16789

TODO test that extra cards in phantoms dont affect the diluted margin, ie the population size remains constant: read the cardManifest and tabulate npops. Alos, could add that to CorlaStateElection.

Precinct Portion

10/05/2026

Boulder has no precinct portion. It also has 1600 redacted ballots. I suspect they used precincts in their redaction, and then removed that column.

Summary pf Redaction for trial counties

Ok heres what I know: none of La Plata, Weld or Morgan had the problem with CVRs (where the same ballotType had different contests, aka card styles), in either the 2026 primary or the 2020 general election. Douglas also did not have that problem in its 2020 CVRs.

In the 2026 Primary, La Plata and Morgan clearly ran our anonymizer which redacted 9 and 25 ballots, respectively. Weld did not run our anonymizer, but they redacted 20 rows by blanking out the votes. Our anonymizer did not find further ballots for Weld it thought should be redacted, but of course it did not have the unredacted CVR file.

In 2020 General, Douglas had 56 redacted ballots and our anonomizer did not find further ballots it thought should be redacted.

In summary, those 4 counties don’t appear to have any of the problems that might mess up our Excel macro. And it seems to me that the current macro will work fine on all of these counties without change. The macro can replace what they are doing now. (Lori, am I missing something about that?)

The macro only does rare styles, not “contest balancing”, so if those counties were willing to again run our python anonomizer, that would be more accurate. And we also think that with the exception of Boulder, no county is currently doing contest balancing, so the macro isn’t making things worse.

I think I will send a pull request to Neal’s repo (or should i use Lori’s?) to change it to put * only where redacted votes exist. So if that is an option for some counties, they can use the python anonomizer and the file format will look the same as with the macro.

If we only have 4 counties, if needed maybe each of us can be at one of the counties when they do the redaction, in case there is a problem.

PS: there is one factoid not particularly relevant to redaction, but in 2026 Primary, La Plata had 50 cvrs in the CVR file that were not present in their manifest that we have in auditcenter. I mention it only because maybe we can alert them so they can double-check it next time.