NeuroNomixer
  • Home
  • Blog
  • Visual Guides
  • Authors
  • Contact
Sign InSign Up
HomeBlogAuthorsContactPrivacy Policy

© 2026 NeuroNomixer — Built with Next.js & Tailwind CSS

Visual Guides/Anonymous Is Harder Than You Think
Data & Analysis

Anonymous Is Harder Than You Think

A clinic deletes every name and publishes its records. You, armed with nothing but a public voter roll, will unmask its patients in three clicks. Then you switch sides and defend the release with k-anonymity, and discover that every unit of privacy is paid for in answers.

Re-identify 3 neighbors (0/3)
Reach k ≥ 5
Try 3 defense settings (0/3)

Sign in to save progress

Removing names is not anonymization

The clinic in the fictional town of Midvale did what most organizations still do: it deleted the name column and called the data anonymous. But ZIP code, age, and gender survived, and those three fields are quasi-identifiers: harmless alone, a fingerprint together. In 2000, Latanya Sweeney estimated that 87 percent of one country's population could be uniquely identified by ZIP code, birth date, and sex alone (Sweeney, 2000). That is a cited historical result, not something this page recomputes. What this page does recompute, on every click, is the same attack in miniature.

How this playground stays honest: both tables below are synthetic, with fictional people, and both are fully visible on this page. Every match count, k value, group size, and utility percentage is computed live in your browser from those visible rows. Nothing is faked.

1 · The attack: link two harmless tables

You are the attacker. On the left, Midvale's public voter roll: names attached to ZIP, age, and gender, as many real voter files are. On the right, the clinic's "anonymized" release. Pick a neighbor and join the tables on the three shared columns. Whenever exactly one record matches, that person's diagnosis is yours. Re-identify 3 people.

Midvale voter roll (public)

Anyone can look these 12 neighbors up. Pick a person to run the join on ZIP + age + gender.

NameZIPAgeGenderAttack
Nora Fielding5480123F
Priya Raman5480234F
Marcus Webb5480133M
Elaine Soto5480142F
Tomas Rivera5480248M
Dana Whitfield5512022F
Omar Haddad5512030M
Grete Lund5512135F
Astrid Berge5480338F
Victor Chen5512143M
Ruth Ambrose5480361F
Felix Njoku5512052M

Midvale Clinic release ("anonymized")

32 discharge records. Names were deleted before publication; ZIP, age, and gender were kept for research value.

NameZIPAgeGenderDiagnosis
removed5480123FAsthma
removed5480126FAnxiety disorder
removed5480229FMigraine
removed5480221MAsthma
removed5480327MBack pain
removed5480131FMigraine
removed5480234FType 2 diabetes
removed5480338FAnxiety disorder
removed5480133MHypertension
removed5480236MBack pain
removed5480339MAsthma
removed5480142FHypertension
removed5480347FType 2 diabetes
removed5480144MType 2 diabetes
removed5480245MHypertension
removed5480248MMigraine
removed5512022FBack pain
removed5512128FAsthma
removed5512024MAnxiety disorder
removed5512025MMigraine
removed5512129MHypertension
removed5512032FAsthma
removed5512135FHypertension
removed5512137FBack pain
removed5512030MType 2 diabetes
removed5512035MAnxiety disorder
removed5512138MMigraine
removed5512041FMigraine
removed5512046FAnxiety disorder
removed5512143FAsthma
removed5512143MBack pain
removed5512143MHypertension

Join result

Pick a neighbor on the left. The join keeps every released record whose ZIP, age, and gender all equal theirs.

Your re-identifications

0

of 9 neighbors who link to exactly one record

The defense has a name: k-anonymity

The attack worked because some rows are unique on (ZIP, age, gender). A release is k-anonymous when every row is indistinguishable from at least k - 1 others on those quasi-identifiers, so the best any linkage attack can do is point at a crowd of k people. You get there by generalizing (54801 becomes district 548**, age 34 becomes 30 to 39) or by suppressing a column outright. The catch: every step that blurs the attacker's view blurs the honest analyst's view too.

2 · The defense: generalize until k ≥ 5

Now you are the data steward, republishing the same 32 records. Coarsen each column until the smallest group of identical rows holds at least 5 people, and watch what each step does to the attack and to the three queries an analyst still needs to answer. There is more than one way to reach k = 5; they do not cost the same utility.

Choose how much detail the release keeps

ZIP code

Age

Gender

The release, as the world now sees it

Same 32 records, published at your chosen detail. An asterisk means the column was removed.

ZIPAgeGenderDiagnosis
5480123FAsthma
5480126FAnxiety disorder
5480229FMigraine
5480221MAsthma
5480327MBack pain
5480131FMigraine
5480234FType 2 diabetes
5480338FAnxiety disorder
5480133MHypertension
5480236MBack pain
5480339MAsthma
5480142FHypertension
5480347FType 2 diabetes
5480144MType 2 diabetes
5480245MHypertension
5480248MMigraine
5512022FBack pain
5512128FAsthma
5512024MAnxiety disorder
5512025MMigraine
5512129MHypertension
5512032FAsthma
5512135FHypertension
5512137FBack pain
5512030MType 2 diabetes
5512035MAnxiety disorder
5512138MMigraine
5512041FMigraine
5512046FAnxiety disorder
5512143FAsthma
5512143MBack pain
5512143MHypertension

k-anonymity of this release

k = 1

target: k ≥ 5

Every published row is identical to at least 0 other rows on (ZIP, age, gender). The release splits into 31 groups; the smallest is (54801, 23, F) with 1 person.

One bar per group of identical rows. Orange bars are groups smaller than 5.

The attack, re-run against this release

9 unique matches

voter-roll neighbors who still link to exactly one record

Utility left for analysts

100%

Mean age per diagnosis±0.0 yr
Patients per ZIP code±0.0 patients
Female share per diagnosis±0.0 pp

Each line is the mean absolute error of that query answered from the release instead of the raw table. Removed columns fall back to the midpoint of the release's age range, an even split across ZIPs, or a 50 percent gender assumption. 100% means every query still comes out exact.

3 · The tradeoff: privacy is bought with utility

Try at least 3 different settings and compare where they land. Full detail sits at k = 1 with perfect utility; total suppression reaches k = 32 and answers nothing. Real releases live on the frontier between them, and choosing the point on that frontier is an ethical decision, not a technical one: it decides whose privacy is protected and which questions can still be answered.

The tradeoff curve you are tracing

Every setting you try lands here: privacy (k) to the right, analyst utility upward. The empty top-right corner is the point of this guide.

0%25%50%75%100%1510162432target k = 5privacy: k-anonymity (smallest group size)utility
below target ktarget reachedcurrent setting0 settings tried
← All GuidesNext Guide →