Parquet Cleaner
A browser-only tool to clean and anonymize a Parquet file. You build an
ordered cleaning pipeline of small, composable steps; a live preview shows —
with full transparency — where each transform succeeds, fails, or has
no effect. Your data never leaves the browser — everything runs
locally on DuckDB-WASM.
Workflow
- Drop a
.parquet file onto the drop zone, or click to pick one. The file is
read lazily (range reads), so even large files open instantly.
- Add cleaning steps from the Cleaning pipeline panel. Steps run top-to-bottom; each
one transforms the output of the one above. Toggle, reorder (▲ ▼) or remove steps anytime.
- Watch the impact badges on each step and the colored before → after sample. Switch the
preview between Original and Cleaned.
- Click Export cleaned Parquet to download the result. Only at this point is
the full file written end-to-end.
Layout & navigation: the Layout bar switches between Default,
50 / 50, and full-width Pipeline or Preview. Pipeline steps are
collapsible — click a step header to expand/collapse it (the step you just added is opened, the
rest collapse); use Expand all / Collapse all. In the preview, click a
column header to add a column rule with that column pre-selected; columns that
already have a step are marked (green underline + dot, with a tooltip listing the steps).
Transparency — OK / failed / no-effect
For the step you are editing, the badges show exact counts over the whole file and the
sample table colors each row:
- Type conversion: green = converted,
red = could not convert → becomes NULL,
grey = value was already NULL (no effect). The three counts always sum to the row total.
- Trim / case / empty→NULL / hashing: how many cells changed vs.
stayed unchanged.
- Row operations (dedup, drop-null, filter): rows in → rows out, and how many
were removed.
Column structure — pattern analysis
To understand a messy column before cleaning it, open Column structure — pattern
analysis, pick a column and click Analyze patterns — or, quicker, click a
column header in the preview and choose Analyze value patterns (the
result opens in this panel for that column). Each value is reduced to a
mask — A = uppercase letter, a = lowercase letter, 9 =
digit, every other character kept literally (Unicode letters incl. umlauts are recognized). The
most frequent masks are listed with their count, share and an example, plus a derived
regex you can copy straight into a Regex replace/extract step. Example:
+49 89 1234 → mask +99 99 9999 → regex
^\+\d{2} \d{2} \d{4}$.
Two views: Exact length keeps the run length (999 ⇒
\d{3}), while Compact collapses any run to 9+
(regex \d+) — so 9, 99, 999 … fold into one
pattern. Toggle between them; null and empty values are reported separately.
Clean & anonymize (heuristic suggestions)
Open Clean & anonymize and click Scan data. A single scan checks the
data for quality issues and for PII, and presents everything in one table — one row per
attribute (column), with a Cleaning column and an
Anonymization column, so you see all suggested rules at a glance and can
Apply them individually, or Apply all suggestions at once (cleaning first, then
anonymization). Whole-table fixes (e.g. exact duplicates) appear as a banner above the table.
A Protection level switch chooses how much is anonymized (cleaning is
always the same). The anonymization column and Apply all follow the selected level:
- Level 1 · Pseudonymize PII — deterministic pseudonyms for
direct identifiers (name, email, phone, IBAN, address, ID …) and sensitive
fields; joins/consistency are preserved. Quasi-identifiers, dates and numeric values stay
unchanged.
- Level 2 · + numeric — Level 1 plus quasi-identifiers (ZIP, city,
country …) and dates, and numeric measures perturbed with
relative ±10% noise — this keeps the sign, zero values, magnitude and 2 decimals
(structure) and the distribution/mean (statistics), but hides the concrete value. (For
additive amount columns you can still switch a step to Coarsen to keep exact
per-category sums.)
- Level 3 · Full anonymization — everything randomized / irreversible: PII →
random synthetic values (no linkage), numbers → Randomize within their
range, free text → synthetic. Only the data structure remains; no re-identification of PII or
numeric values.
The Cleaning suggestions run locally on a sample plus a few
full-table aggregates and covers: stray whitespace (→ Trim),
empty strings that should be NULL (→ Empty → NULL), numbers stored as
text (→ Parse number, with the decimal separator auto-detected),
dates stored as text (→ Parse date, with the format auto-detected),
boolean-looking columns (→ Convert type), entirely empty
columns (→ Drop column) and exact duplicate rows (→ Remove duplicates).
Each suggestion shows a confidence and a short reason; Apply all adds
them in a sensible order (trim → empty→null → parse/convert → de-duplicate → drop). The live
preview and per-step impact panel show exactly what each step does — review before exporting.
PII detection
The PII / sensitivity column builds on top of the cleaning: by default it samples
the cleaned data (toggle Original / Cleaned in the PII source switch), so
parsed dates, trimmed strings and '' → NULL conversions make detection cleaner. It
finds columns
that likely contain personal data. Detection is two-stage and runs entirely locally: by
column name (e.g. email, telefon, iban,
geburtsdatum, plz) and by content — a sample of values
is matched against format patterns (email, IBAN, phone, credit-card incl. Luhn check, UUID, IP).
Content evidence (≥ 60 % of sampled values) wins over the name, so even a cryptically named
column is caught.
Detected columns are classified into three sensitivity levels, shown as colored badges in the
list and in the preview column headers:
- Direct identifier — identifies a person on its own (name, email, phone,
IBAN, tax/ID number, address, customer ID).
- Quasi-identifier — identifies in combination with others (date of birth,
postal code, city, gender, age, nationality).
- Sensitive (special category) — health, religion, political/union, income.
Each column comes with a suggested anonymization rule appropriate for its type
(e.g. email → Synthetic email, person name → Synthetic name, recurring business party →
Synthetic data in consistent mode, IBAN → Hash, date of birth → Parse date + generalize
to year, income → Round/bucket).
Click Apply to add that step to the
pipeline, or Apply all suggestions for every detected column at once. The detection is a
heuristic starting point — always review the result before exporting.
Cleaning steps
Row-based
- Remove exact duplicates — drops rows that are identical across all columns
(
SELECT DISTINCT *).
- Remove duplicates by key columns — a duplicate = same values in the chosen
key columns; keeps the first or last per group (optionally ordered by a column).
- Drop null / empty rows — drops a row if any selected column is NULL (and,
optionally, empty / whitespace).
- Filter rows — a free SQL
WHERE expression over the original
column names.
Column-based
- Convert type — safe conversion; values that don't fit become NULL (and are
counted as failures). For DATE / TIMESTAMP / TIME targets you can enter one
or more date/time patterns (e.g.
DD.MM.YYYY). Several patterns
(one per line) are tried in order, so a column that mixes spellings —
DD.MM.YYYY and MM/DD/YYYY — is parsed correctly per value.
Tokens: YYYY YY · MM (month) DD ·
HH (24h) hh (12h) mm (minutes) SS;
or paste a raw strptime format like %d.%m.%Y. Leave empty for automatic ISO
parsing. (Implemented with DuckDB try_strptime.)
- Parse number (locale) — for numbers stored as text. Pick the decimal
separator (German
1.234,56 or US 1,234.56); thousand separators,
spaces and currency symbols are stripped automatically, then the value is converted to
DOUBLE / DECIMAL / INTEGER. Non-numbers become NULL (counted as failures).
- Parse date — for dates stored as text. Choose the target type
(Date / Timestamp / Time) and enter one or more date/time
patterns, or pick a preset (DE
DD.MM.YYYY, US MM/DD/YYYY,
ISO, …). Several patterns (one per line) are tried in order, so a column mixing spellings is
parsed correctly per value; leave empty for automatic ISO parsing. Unparseable values become
NULL (counted as failures). The Generalize option reduces the parsed date to
the start of the month / quarter / year (a privacy-friendly way to coarsen
quasi-identifiers like a birth date). Implemented with DuckDB try_strptime +
date_trunc.
- Regex replace (search & replace) — DuckDB
regexp_replace
with a regex pattern and a replacement (use \1 for capture groups); flags for
global and case-insensitive. Presets cover common cleanups (collapse
spaces, digits only, strip [..] tags). The headline use case for VARCHAR
cleaning.
- Regex extract — pull out a match or capture group
(
regexp_extract), e.g. the domain from an email (@(.*)$, group 1).
Rows that don't match become NULL.
- Trim & collapse whitespace, Change case (UPPER/lower),
Empty → NULL.
- Rename / Drop column.
Anonymization & pseudonymization
Two general modes (selectable per step): Deterministic — the same input always
yields the same output, so joins and repeated-value consistency are kept (but the repeated
pseudonym can still be linked via other attributes); Random — every row is
independent, which breaks that linkage but destroys consistency. Determinism is derived from
hash(value + salt); randomness from a fresh draw per row (so each run differs).
- Replace with synthetic data (Faker / consistent) — replaces values with
realistic synthetic data while keeping the structure; NULLs stay NULL. Pick what to
generate (Full/First/Last name, Company, Email, Phone, City, Country, Street, ZIP,
IBAN (German, with a valid mod-97 check digit), BIC, Text / notes
(lorem ipsum), or Auto entity) and a method:
- Consistent & collision-free (k-anon) — the analytics-preserving
choice. Each distinct value maps to one stable, collision-free pseudonym (via a
salted
dense_rank), so GROUP BY totals stay exact and join keys
are preserved. For Full name / Company / Auto entity it is type-aware (Person → person
name, Organization → “… GmbH/AG”). Public authorities (Finanzamt, Stadt, Krankenkasse …)
are pseudonymized as organizations by default; tick keep public authorities to
leave them unchanged (e.g. for reports where they aren't personal data). For
Email, Phone, ZIP,
Street it generates collision-free values of that shape (e.g.
anna.mueller@example.org, 00001). The k
parameter merges values seen fewer than k times into a shared “Sammel” bucket so no
individual is singled out; k = 0 (or 1) disables bucketing.
- Deterministic — per value, same input → same fake (joins kept, but two
different values may collide). Random — every row independent. Example:
Thomas Müller → Fritz Schmidt.
Consistent mode needs a large enough value space, so it is offered for Full name, Company,
Auto entity, Email, Phone, ZIP, Street and IBAN; BIC, Text/notes and First/Last name, City,
Country use deterministic.
- Coarsen amounts (sum-preserving) — rounds an amount column to remove unique
value fingerprints (e.g. exact salaries) while keeping the exact sum within each
group (default: per category) — so category/monthly totals are unchanged. Run
Recompute running balance afterwards to keep the saldo consistent.
- Hash / pseudonymize —
sha256(value + salt) (deterministic).
Keep the salt secret; weak for small value ranges (e.g. gender) — use generalization there.
- Shuffle / bootstrap — replaces each value with another value drawn from the
same column. The column's distribution is preserved exactly; the row link is broken.
Deterministic = stable mapping, Random = bootstrap. Works for numbers, dates and categories
(loads the column into memory).
- Round / bucket (number) — coarsens to a multiple (microaggregation);
deterministic, keeps aggregates roughly and yields k-anonymity. Add noise
(number) — zero-centred jitter, stays a number (deterministic or random).
To generalize dates to month / quarter / year, use the Generalize option of
Parse date above.
Note: pseudonymized data is still personal data. For real anonymity combine techniques (e.g.
faker for direct identifiers + generalization for quasi-identifiers like ZIP/birth date) and
check the column structure / k-anonymity. Differential privacy (calibrated noise with formal
guarantees) is a possible future addition.
Notes & limitations (v1)
- Column pickers list the file's original columns. If you rename or
drop a column early and a later step still references the old name, that step will
error — reorder so renames/drops come last, or adjust the reference.
- Regex and number-parsing steps operate on the column's text form. On an
already-typed column the result becomes VARCHAR — run them before a type
conversion (the pipeline order is up to you). For parsing dates use the
Convert type patterns rather than regex.
- Exact-duplicate removal compares all columns; nested types (LIST/STRUCT/MAP) may not be
comparable and can cause an error — drop or convert them first.
- Hashing is pseudonymization, not guaranteed anonymity: with a known salt and small
value space, values can be brute-forced. Combine with generalization for stronger privacy
(planned).
- DuckDB-WASM is loaded from a public CDN, so internet access is needed on first load; the
file itself is never uploaded.
Parquet Cleaner
Ein reines Browser-Werkzeug, um eine Parquet-Datei zu bereinigen und zu
anonymisieren. Du baust eine geordnete Bereinigungs-Pipeline aus
kleinen, kombinierbaren Schritten; eine Live-Vorschau zeigt vollständig transparent, wo jede
Umwandlung greift, fehlschlägt oder ohne Wirkung bleibt.
Deine Daten verlassen den Browser nicht — alles läuft lokal auf DuckDB-WASM.
Ablauf
- Eine
.parquet-Datei in den Ablagebereich ziehen oder klicken, um eine
auszuwählen. Die Datei wird lazy gelesen (Bereichszugriffe), sodass selbst große Dateien
sofort öffnen.
- Bereinigungsschritte im Bereich Bereinigungs-Pipeline hinzufügen. Die Schritte
laufen von oben nach unten; jeder verarbeitet das Ergebnis des vorherigen. Schritte lassen
sich jederzeit ein-/ausschalten, umsortieren (▲ ▼) oder entfernen.
- Die Wirkungs-Markierungen an jedem Schritt und die eingefärbte Vorher-→-Nachher-Stichprobe
beobachten. Die Vorschau lässt sich zwischen Original und
Bereinigt umschalten.
- Auf Bereinigtes Parquet exportieren klicken, um das Ergebnis
herunterzuladen. Erst zu diesem Zeitpunkt wird die vollständige Datei geschrieben.
Layout & Navigation: Die Leiste Layout wechselt zwischen Standard,
50 / 50 sowie Pipeline oder Vorschau über die volle Breite.
Pipeline-Schritte sind einklappbar — ein Klick auf die Kopfzeile klappt einen Schritt auf oder zu
(der zuletzt hinzugefügte wird geöffnet, die übrigen eingeklappt); dazu gibt es
Alle ausklappen / Alle einklappen. In der Vorschau fügt ein Klick auf eine
Spaltenüberschrift eine Spaltenregel mit dieser Spalte hinzu; Spalten mit
bereits vorhandenem Schritt sind markiert (grüne Unterstreichung und Punkt, mit einem Tooltip,
der die Schritte auflistet).
Transparenz — OK / fehlgeschlagen / ohne Wirkung
Für den gerade bearbeiteten Schritt zeigen die Markierungen exakte Anzahlen über die
gesamte Datei, und die Stichprobentabelle färbt jede Zeile ein:
- Typkonvertierung: grün = konvertiert,
rot = nicht konvertierbar → wird NULL,
grau = Wert war bereits NULL (ohne Wirkung). Die drei Zahlen ergeben immer die
Gesamtzeilenzahl.
- Trim / Groß-Kleinschreibung / Leer→NULL / Hashing: wie viele Zellen sich
geändert haben und wie viele unverändert blieben.
- Zeilenoperationen (Dedup, Null entfernen, Filter): Zeilen hinein → Zeilen
heraus, und wie viele entfernt wurden.
Spaltenstruktur — Musteranalyse
Um eine unsaubere Spalte vor dem Bereinigen zu verstehen, öffne
Spaltenstruktur — Musteranalyse, wähle eine Spalte und klicke auf
Muster analysieren — oder schneller: klicke auf eine
Spaltenüberschrift in der Vorschau und wähle Wertemuster analysieren
(das Ergebnis öffnet sich für diese Spalte in diesem Bereich). Jeder Wert wird auf eine Maske
reduziert — A = Großbuchstabe, a = Kleinbuchstabe, 9 =
Ziffer, jedes andere Zeichen bleibt wörtlich erhalten (Unicode-Buchstaben inklusive Umlaute
werden erkannt). Die häufigsten Masken werden mit Anzahl, Anteil und einem Beispiel gelistet,
dazu ein abgeleiteter regulärer Ausdruck, den du direkt in einen Schritt
Regex ersetzen/extrahieren übernehmen kannst. Beispiel:
+49 89 1234 → Maske +99 99 9999 → Regex
^\+\d{2} \d{2} \d{4}$.
Zwei Sichten: Exakte Länge behält die Lauflänge (999 ⇒
\d{3}), während Kompakt jede Folge zu 9+
zusammenfasst (Regex \d+) — so fallen 9, 99,
999 … zu einem Muster zusammen. Zwischen beiden lässt sich umschalten; Null- und
Leerwerte werden getrennt ausgewiesen.
Bereinigen & anonymisieren (heuristische Vorschläge)
Öffne Bereinigen & anonymisieren und klicke auf Daten prüfen. Ein
einziger Durchlauf prüft die Daten auf Qualitätsprobleme und auf PII und stellt alles in
einer Tabelle dar — eine Zeile je Attribut (Spalte), mit einer Spalte
Bereinigung und einer Spalte Anonymisierung. So siehst du alle
vorgeschlagenen Regeln auf einen Blick und kannst sie einzeln anwenden oder mit
Alle Vorschläge anwenden auf einmal (zuerst Bereinigung, dann Anonymisierung).
Korrekturen für die gesamte Tabelle (etwa exakte Duplikate) erscheinen als Banner über der
Tabelle.
Ein Schalter für die Schutzstufe bestimmt, wie viel anonymisiert wird
(die Bereinigung bleibt immer gleich). Die Anonymisierungsspalte und Alle anwenden
folgen der gewählten Stufe:
- Stufe 1 · PII pseudonymisieren — deterministische Pseudonyme für
direkte Identifikatoren (Name, E-Mail, Telefon, IBAN, Adresse, Ausweisnummer …)
und sensible Felder; Verknüpfbarkeit und Konsistenz bleiben erhalten.
Quasi-Identifikatoren, Datumsangaben und numerische Werte bleiben unverändert.
- Stufe 2 · + numerisch — Stufe 1 plus Quasi-Identifikatoren (PLZ,
Ort, Land …) und Datumsangaben, außerdem werden numerische Kennzahlen mit
relativem Rauschen von ±10 % verändert — das erhält Vorzeichen, Nullwerte,
Größenordnung und zwei Nachkommastellen (Struktur) sowie Verteilung und Mittelwert
(Statistik), verbirgt aber den konkreten Wert. (Für additive Betragsspalten kannst du einen
Schritt weiterhin auf Vergröbern umstellen, um exakte Summen je Kategorie zu
erhalten.)
- Stufe 3 · Vollständige Anonymisierung — alles wird zufällig und
unumkehrbar ersetzt: PII → zufällige synthetische Werte (keine Verknüpfbarkeit),
Zahlen → Zufallswert innerhalb ihres Wertebereichs, Freitext → synthetisch. Nur die
Datenstruktur bleibt; weder PII noch numerische Werte lassen sich re-identifizieren.
Die Bereinigungs-Vorschläge entstehen lokal aus einer Stichprobe plus einigen
Aggregaten über die gesamte Tabelle und decken ab: überflüssige Leerzeichen
(→ Trim), leere Zeichenketten, die NULL sein sollten (→ Leer → NULL),
als Text gespeicherte Zahlen (→ Zahl parsen, mit automatisch erkanntem
Dezimaltrennzeichen), als Text gespeicherte Datumsangaben (→ Datum parsen, mit
automatisch erkanntem Format), boolesch wirkende Spalten (→ Typ konvertieren),
vollständig leere Spalten (→ Spalte entfernen) und exakte
Duplikatzeilen (→ Duplikate entfernen). Jeder Vorschlag zeigt eine
Konfidenz und eine kurze Begründung; Alle anwenden fügt sie in
sinnvoller Reihenfolge hinzu (Trim → Leer→NULL → Parsen/Konvertieren → Duplikate → Entfernen).
Live-Vorschau und der Wirkungsbereich je Schritt zeigen genau, was jeder Schritt tut — bitte vor
dem Export prüfen.
PII-Erkennung
Die Spalte PII / Sensibilität setzt auf der Bereinigung auf: Standardmäßig zieht
sie ihre Stichprobe aus den bereinigten Daten (umschaltbar über
Original / Bereinigt im Schalter für die PII-Quelle), sodass geparste Datumsangaben,
getrimmte Zeichenketten und '' → NULL-Umwandlungen die Erkennung verbessern.
Gefunden werden Spalten, die wahrscheinlich personenbezogene Daten enthalten. Die Erkennung
arbeitet zweistufig und vollständig lokal: über den Spaltennamen (etwa
email, telefon, iban, geburtsdatum,
plz) und über den Inhalt — eine Stichprobe der Werte wird gegen
Formatmuster geprüft (E-Mail, IBAN, Telefon, Kreditkarte inklusive Luhn-Prüfung, UUID, IP).
Inhaltliche Evidenz (≥ 60 % der geprüften Werte) schlägt den Namen, sodass auch eine kryptisch
benannte Spalte erkannt wird.
Erkannte Spalten werden in drei Sensibilitätsstufen eingeordnet, dargestellt als farbige
Markierungen in der Liste und in den Spaltenüberschriften der Vorschau:
- Direkter Identifikator — identifiziert eine Person für sich allein (Name,
E-Mail, Telefon, IBAN, Steuer-/Ausweisnummer, Adresse, Kundennummer).
- Quasi-Identifikator — identifiziert in Kombination mit anderen
(Geburtsdatum, Postleitzahl, Ort, Geschlecht, Alter, Staatsangehörigkeit).
- Sensibel (besondere Kategorie) — Gesundheit, Religion, politische
Ausrichtung bzw. Gewerkschaft, Einkommen.
Zu jeder Spalte gehört eine vorgeschlagene Anonymisierungsregel, die zu ihrem
Typ passt (etwa E-Mail → synthetische E-Mail, Personenname → synthetischer Name, wiederkehrender
Geschäftspartner → synthetische Daten im Modus konsistent, IBAN → Hash, Geburtsdatum →
Datum parsen und auf das Jahr generalisieren, Einkommen → Runden/Gruppieren).
Ein Klick auf Anwenden fügt diesen Schritt zur Pipeline hinzu, Alle Vorschläge
anwenden übernimmt alle erkannten Spalten auf einmal. Die Erkennung ist ein heuristischer
Ausgangspunkt — bitte das Ergebnis vor dem Export immer prüfen.
Bereinigungsschritte
Zeilenbasiert
- Exakte Duplikate entfernen — entfernt Zeilen, die über alle Spalten hinweg
identisch sind (
SELECT DISTINCT *).
- Duplikate über Schlüsselspalten entfernen — ein Duplikat sind gleiche Werte
in den gewählten Schlüsselspalten; behält je Gruppe den ersten oder letzten Eintrag
(wahlweise nach einer Spalte sortiert).
- Zeilen mit leeren Werten entfernen — entfernt eine Zeile, sobald eine
ausgewählte Spalte NULL ist (wahlweise auch leer bzw. nur Leerzeichen).
- Zeilen filtern — ein freier SQL-
WHERE-Ausdruck über die
ursprünglichen Spaltennamen.
Spaltenbasiert
- Typ konvertieren — sichere Konvertierung; nicht passende Werte werden NULL
(und als Fehlschläge gezählt). Für die Ziele DATE / TIMESTAMP / TIME kannst
du ein oder mehrere Datums-/Zeitmuster angeben (etwa
DD.MM.YYYY). Mehrere Muster (eines je Zeile) werden der Reihe nach probiert,
sodass eine Spalte mit gemischten Schreibweisen — DD.MM.YYYY und
MM/DD/YYYY — je Wert korrekt geparst wird. Platzhalter:
YYYY YY · MM (Monat) DD ·
HH (24 h) hh (12 h) mm (Minuten) SS;
alternativ ein rohes strptime-Format wie %d.%m.%Y einfügen. Leer lassen für
automatisches ISO-Parsen. (Umgesetzt mit DuckDB try_strptime.)
- Zahl parsen (Gebietsschema) — für als Text gespeicherte Zahlen. Wähle das
Dezimaltrennzeichen (deutsch
1.234,56 oder US 1,234.56);
Tausendertrennzeichen, Leerzeichen und Währungssymbole werden automatisch entfernt,
anschließend wird der Wert nach DOUBLE / DECIMAL / INTEGER konvertiert. Nicht-Zahlen werden
NULL (als Fehlschläge gezählt).
- Datum parsen — für als Text gespeicherte Datumsangaben. Wähle den Zieltyp
(Datum / Zeitstempel / Uhrzeit) und gib ein oder mehrere
Datums-/Zeitmuster an oder wähle eine Vorlage (DE
DD.MM.YYYY,
US MM/DD/YYYY, ISO, …). Mehrere Muster (eines je Zeile) werden der Reihe nach
probiert, sodass eine Spalte mit gemischten Schreibweisen je Wert korrekt geparst wird; leer
lassen für automatisches ISO-Parsen. Nicht parsbare Werte werden NULL (als Fehlschläge
gezählt). Die Option Generalisieren reduziert das geparste Datum auf den
Beginn von Monat / Quartal / Jahr — eine datenschutzfreundliche Art, um
Quasi-Identifikatoren wie ein Geburtsdatum zu vergröbern. Umgesetzt mit DuckDB
try_strptime + date_trunc.
- Regex ersetzen (Suchen & Ersetzen) — DuckDB
regexp_replace mit Suchmuster und Ersetzung (\1 für
Fanggruppen); Schalter für global und Groß-/Kleinschreibung ignorieren.
Vorlagen decken häufige Aufräumarbeiten ab (Leerzeichen zusammenfassen, nur Ziffern,
[..]-Tags entfernen). Der wichtigste Anwendungsfall beim Bereinigen von
VARCHAR-Spalten.
- Regex extrahieren — holt einen Treffer oder eine Fanggruppe heraus
(
regexp_extract), etwa die Domain aus einer E-Mail (@(.*)$,
Gruppe 1). Nicht passende Zeilen werden NULL.
- Leerzeichen kürzen & zusammenfassen,
Groß-/Kleinschreibung ändern (GROSS/klein),
Leer → NULL.
- Spalte umbenennen / entfernen.
Anonymisierung & Pseudonymisierung
Zwei grundsätzliche Modi (je Schritt wählbar): Deterministisch — dieselbe
Eingabe ergibt immer dieselbe Ausgabe, sodass Verknüpfungen und die Konsistenz wiederkehrender
Werte erhalten bleiben (das wiederkehrende Pseudonym lässt sich allerdings über andere Attribute
weiterhin verknüpfen); Zufällig — jede Zeile ist unabhängig, was diese
Verknüpfung bricht, aber die Konsistenz zerstört. Determinismus entsteht aus
hash(Wert + Salt), Zufall aus einer neuen Ziehung je Zeile (jeder Lauf
unterscheidet sich also).
- Durch synthetische Daten ersetzen (Faker / konsistent) — ersetzt Werte
durch realistische synthetische Daten und behält die Struktur; NULL bleibt NULL. Wähle,
was erzeugt werden soll (vollständiger Name / Vorname / Nachname, Firma, E-Mail,
Telefon, Ort, Land, Straße, PLZ, IBAN (deutsch, mit gültiger Mod-97-Prüfziffer),
BIC, Text / Notizen (Lorem ipsum) oder Auto-Entität) und eine
Methode:
- Konsistent & kollisionsfrei (k-Anonymität) — die Wahl, die
Auswertbarkeit erhält. Jeder eindeutige Wert wird auf ein stabiles,
kollisionsfreies Pseudonym abgebildet (über einen gesalzenen
dense_rank),
sodass GROUP BY-Summen exakt bleiben und Verknüpfungsschlüssel erhalten
werden. Für vollständigen Namen / Firma / Auto-Entität arbeitet die Methode
typbewusst (Person → Personenname, Organisation → „… GmbH/AG“). Behörden (Finanzamt,
Stadt, Krankenkasse …) werden standardmäßig als Organisationen pseudonymisiert;
aktiviere Behörden beibehalten, um sie unverändert zu lassen (etwa für
Auswertungen, in denen sie keine personenbezogenen Daten sind). Für
E-Mail, Telefon, PLZ, Straße werden kollisionsfreie Werte in der jeweiligen
Form erzeugt (etwa anna.mueller@example.org, 00001). Der
Parameter k fasst Werte, die seltener als k-mal vorkommen, zu einem
gemeinsamen Sammel-Eintrag zusammen, sodass niemand einzeln heraussticht;
k = 0 (oder 1) schaltet diese Bündelung ab.
- Deterministisch — je Wert, gleiche Eingabe → gleicher Fake
(Verknüpfungen bleiben, zwei verschiedene Werte können aber kollidieren).
Zufällig — jede Zeile unabhängig. Beispiel:
Thomas Müller → Fritz Schmidt.
Der konsistente Modus braucht einen ausreichend großen Wertebereich und wird daher für
vollständigen Namen, Firma, Auto-Entität, E-Mail, Telefon, PLZ, Straße und IBAN angeboten;
BIC, Text/Notizen sowie Vor-/Nachname, Ort und Land nutzen den deterministischen Modus.
- Beträge vergröbern (summenerhaltend) — rundet eine Betragsspalte, um
eindeutige Wertefingerabdrücke zu entfernen (etwa exakte Gehälter), und erhält dabei die
exakte Summe innerhalb jeder Gruppe (standardmäßig je Kategorie) — Monats-
und Kategoriesummen bleiben also unverändert. Führe anschließend
Laufenden Saldo neu berechnen aus, damit der Saldo stimmig bleibt.
- Hashen / pseudonymisieren —
sha256(Wert + Salt)
(deterministisch). Das Salt geheim halten; bei kleinen Wertebereichen (etwa Geschlecht)
schwach — dort besser generalisieren.
- Mischen / Bootstrap — ersetzt jeden Wert durch einen anderen Wert aus
derselben Spalte. Die Verteilung der Spalte bleibt exakt erhalten, die Zeilenzuordnung wird
gebrochen. Deterministisch = stabile Zuordnung, Zufällig = Bootstrap. Funktioniert für
Zahlen, Datumsangaben und Kategorien (lädt die Spalte in den Speicher).
- Runden / gruppieren (Zahl) — vergröbert auf ein Vielfaches
(Mikroaggregation); deterministisch, erhält Aggregate näherungsweise und erzeugt
k-Anonymität. Rauschen hinzufügen (Zahl) — um null zentrierte Streuung,
das Ergebnis bleibt eine Zahl (deterministisch oder zufällig).
Um Datumsangaben auf Monat / Quartal / Jahr zu generalisieren, nutze die Option
Generalisieren von Datum parsen weiter oben.
Hinweis: Pseudonymisierte Daten bleiben personenbezogene Daten. Für echte Anonymität mehrere
Techniken kombinieren (etwa Faker für direkte Identifikatoren + Generalisierung für
Quasi-Identifikatoren wie PLZ oder Geburtsdatum) und die Spaltenstruktur bzw. die k-Anonymität
prüfen. Differential Privacy (kalibriertes Rauschen mit formalen Garantien) ist eine mögliche
künftige Ergänzung.
Hinweise & Grenzen (v1)
- Die Spaltenauswahl listet die ursprünglichen Spalten der Datei. Wenn du eine Spalte
früh umbenennst oder entfernst und ein späterer Schritt noch den alten
Namen verwendet, schlägt dieser Schritt fehl — sortiere so um, dass Umbenennungen und
Entfernungen zuletzt kommen, oder passe die Referenz an.
- Regex- und Zahl-Parsing-Schritte arbeiten auf der Text-Form der Spalte. Bei einer
bereits typisierten Spalte wird das Ergebnis VARCHAR — führe sie also vor
einer Typkonvertierung aus (die Reihenfolge der Pipeline bestimmst du). Zum Parsen von
Datumsangaben besser die Muster von Typ konvertieren nutzen statt Regex.
- Das Entfernen exakter Duplikate vergleicht alle Spalten; verschachtelte Typen
(LIST/STRUCT/MAP) sind unter Umständen nicht vergleichbar und können einen Fehler
verursachen — solche Spalten vorher entfernen oder konvertieren.
- Hashing ist Pseudonymisierung, keine garantierte Anonymität: mit bekanntem Salt und
kleinem Wertebereich lassen sich Werte durch Ausprobieren ermitteln. Für stärkeren Schutz mit
Generalisierung kombinieren (geplant).
- DuckDB-WASM wird von einem öffentlichen CDN geladen, beim ersten Laden ist daher ein
Internetzugang nötig; die Datei selbst wird niemals hochgeladen.