CommunityCodierung & Entwicklunggithub.com

ZrobDev/Datenbereinigung

Verwenden, wenn eine neue CSV-, Parquet- oder XLSX-Datei vor der Bearbeitung profiliert werden muss, oder beim Bereinigen, Deduplizieren oder Normalisieren von Datensätzen, beim Umwandeln von Daten/Währungen/IDs oder beim Abgleichen einer Quelle der Wahrheit mit einer abgeleiteten Datei (OCR-gescannte Dokumente vs. Systemexport, Upload vs. DB). Deckt ab: Abweichungen der Zeilenanzahl, verlorene führende Nullen, Duplikate, Kontrollsummen, Anti-Joins und Ausnahmeberichte.

Was ist Datenbereinigung?

Dieses Skill ist für Datenbereinigung und -abgleich konzipiert. Es wird aktiviert, wenn eine neue CSV-, Parquet- oder XLSX-Dateie erstmals profiliert werden muss, oder bei Aufgaben wie Bereinigen, Deduplizieren, Normalisieren von Datensätzen, Umwandeln von Datumsformaten, Währungen oder IDs sowie beim Abgleich einer Quelle der Wahrheit mit einer abgeleiteten Datei (z. B. OCR-Scans vs. Systemexport). Der Workflow ist strikt in fünf Phasen unterteilt: Profilierung (schreibgeschützt), Typ- und Parsing-Festlegung, Normalisierung, Deduplizierung und Reconciliations-Audit. Jeder Schritt ist zählbar und meldet Änderungen; es wird nie stillschweigend korrigiert. Das Skill unterstützt DuckDB 2.0 SQL und Polars 2.x Lazy API für lokale Dateien. Es enthält detaillierte Anleitungen für explizite Datumsparsing, Währungshandhabung (Vermeidung von Floats), deterministische Deduplizierung und einen mehrstufigen Abgleich mit Anti-Joins und Ausnahmeklassifizierung. Ein umfassender Ausnahmebericht mit Kontrollsummen, Balance-Identität und Vorschlägen für manuelle Korrekturen wird erstellt, bevor Ergebnisse ausgegeben werden.

Funktioniert mit~Claude Code~Codex CLI~Cursor
Part ofMobile
npx skills add https://github.com/ZrobDev/data-engineering-skills/tree/HEAD/skills/data-cleaning

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Datenbereinigung und -abgleich

Standardwerkzeuge: DuckDB 2.0 SQL oder Polars 2.x Lazy API (scan_csv, scan_parquet) für lokale Dateien. Pandas nur, wenn eine Bibliothek es erzwingt. Python über uv, Linting mit ruff. Überprüfe alle API-Details, die sich in Polars 2.0 oder DuckDB 2.0 geändert haben, anhand der aktuellen Dokumentation, bevor du dich darauf verlässt (siehe references/landscape-2026-11.md).

Niemals stillschweigend korrigieren

Jede Konvertierung, Löschung, Standardzuweisung oder Zusammenführung wird gezählt und gemeldet. Ein Bereinigungsschritt ist (rows_in, rows_out, rows_changed, reason). Fehlgeschlagene Typumwandlungen werden zu NULL plus einer Zählung, niemals zu einer gelöschten Zeile und niemals zu einem geschätzten Wert. Lasse die Rohdaten unberührt; schreibe die bereinigte Ausgabe in einen neuen Pfad. Wenn die Zählungen eines Schritts überraschen, stoppe und melde, anstatt fortzufahren.

Vorgehen

  1. Profilieren (schreibgeschützt). 2. Schlüssel, Körnung und Typen festlegen. 3. Bereinigen in einer Pipeline aus kleinen, gezählten Schritten. 4. Abgleichen, wenn zwei Quellen vorliegen. 5. Ausnahmen plus Zusammenfassung mit allen Zählungen ausgeben.

1. Vor dem Bearbeiten profilieren

Lese jede Spalte zuerst als Text (all_varchar=true in DuckDB, infer_schema=False in Polars), da die Inferenz anhand einer Stichprobe stillschweigend 00123 in 123 verwandelt und gemischte Spalten in den Typ der ersten Zeile umwandelt. Berechne dann pro Spalte: Zeilenanzahl, Null/Leerstringrate, Anzahl unterschiedlicher Werte, Min/Max (als Text und als geparster Wert), kürzeste/längste Länge und Anteil der Werte, die einem Typmuster entsprechen (Integer, Dezimalzahl, ISO-Datum, Sonstiges). DuckDB SUMMARIZE erledigt das meiste in einem Aufruf.

Halte vor der Bereinigung fest: Gesamtzeilen, Anzahl unterschiedlicher Kandidatenschlüssel, Zeilen pro Schlüssel (Maximum) und die exakt vorgefundenen Kopfzeilen (nachgestellte Leerzeichen, BOM, doppelte Namen). Ein Kandidatenschlüssel ist nur ein Schlüssel, wenn die Anzahl unterschiedlicher Werte nach Normalisierung der Zeilenanzahl entspricht; teste dies, nimm es nicht an.

Prüfe auf: zeilenweise Duplikate, wiederholte Kopfzeilen in der Mitte der Datei, Fußzeilen/Summenzeilen innerhalb der Daten, Platzhalterwerte ("N/A", "-", "0000-00-00", 9999-12-31), gemischte Kodierungen und numerische Spalten, die eigentlich IDs sind.

2. Typen und Parsing

  • IDs, PLZ/Postleitzahlen, Kontonummern und Telefonnummern sind immer Zeichenketten. Speichere eine Auffüllung auf bekannte Breite nur dann als Regel (lpad auf die bekannte Breite), wenn die Breite dokumentiert ist; ansonsten belasse sie wie gelesen.
  • Datumsangaben: Parse mit einem expliziten Format pro Spalte (try_strptime / str.to_date(format, strict=False)). Lasse den Motor niemals die Reihenfolge von Tag/Monat erraten. Mehrdeutige Werte (03/04/2026) ohne dokumentierte Reihenfolge sind eine Ausnahme, kein Münzwurf. Lege die Zeitzonenentscheidung explizit fest.
  • Geldbeträge: Parse in ganzzahlige Untereinheiten oder DECIMAL(p,s), niemals in Floats. Entferne Währungssymbole und Tausendertrennzeichen nach Gebietsschemaregel: 1.234,56 und 1,234.56 sind unterschiedliche Gebietsschemata – entscheide also pro Quelle und stelle sicher, dass jeder Wert dem gewählten Muster entspricht. Klammern und nachgestelltes Minus sind negativ. Halte die Währung pro Zeile fest; summiere nicht über verschiedene Währungen hinweg.
  • Booleans und Enums: Kartiere von einer expliziten Tabelle; nicht kartierte Werte gehen in die Ausnahmen.
  • Zähle nach jeder Umwandlung non-null before minus non-null after. Diese Zahl ist die Anzahl der fehlgeschlagenen Konvertierungen und wird im Bericht ausgewiesen.

3. Normalisierung

Wende die Normalisierung auf einen abgeleiteten Match-Schlüssel an, nicht auf die ursprüngliche Spalte, sodass der Rohwert erhalten bleibt: Unicode NFKC, Trimmen, Zusammenziehen interner Leerzeichen, Fallnormalisierung, Entfernen von Nullbreiten- und geschützten Leerzeichen. NFKC ist verlustbehaftet (Ligaturen, Vollbreitenformen, hochgestellte Zeichen) – das ist für den Abgleich beabsichtigt und für die Anzeige falsch. Entferne bei IDs auch Trennzeichen (-, /, Leerzeichen) und lege die Behandlung von O/0 und I/1 explizit fest. NFKC ist im DuckDB-Kern-SQL nicht enthalten; führe es in Polars/Python aus oder registriere eine UDF (überprüfe die aktuelle Unterstützung).

4. Deduplizierung

  • Exakte Duplikate: Entfernen mit Zählung; behalte die Zeilennummer der überlebenden Zeile aus der Quelldatei.
  • Duplikate nach Schlüssel: Entscheide zuerst, ob es sich um echte Wiederholungen oder getrennte Ereignisse handelt (gleiche Rechnungsnummer, unterschiedlicher Betrag ist ein Konflikt, kein Duplikat).
  • Die Auswahl des Überlebenden muss deterministisch sein und angegeben werden: ROW_NUMBER() OVER (PARTITION BY key ORDER BY updated_at DESC NULLS LAST, completeness DESC, source_row DESC) = 1 (DuckDB QUALIFY). Beende die ORDER BY-Klausel immer mit einem eindeutigen Tiebreaker wie der Quellzeilennummer, da Gleichstände sonst durch eine willkürliche Scan-Reihenfolge aufgelöst werden. Verwende in Polars sort(...) dann unique(subset, keep="first", maintain_order=True).
  • Fuzzy-Deduplizierung ist ein Kandidatengenerator, niemals eine automatische Zusammenführung: Blocke auf einem billigen Schlüssel (normalisierte PLZ, erste 3 Buchstaben, Jahr), bewerte innerhalb der Blöcke, akzeptiere automatisch nur oberhalb einer hohen Schwelle mit einem exakten Sekundärfeld, das übereinstimmt, und sende das mittlere Band an einen Menschen zum Bearbeiten. Melde die Schwelle und die Anzahl.

5. Reconciliations-Audit

Quelle der Wahrheit = A, abgeleitet = B (z. B. Systemexport vs. OCR-gescannte Dokumente). Sage niemals „B ist falsch“, bevor du überprüft hast, ob der Fehler in der Extraktion oder im Schlüssel liegt.

  1. Kontrollsummen zuerst. Zeilenanzahl und Summe jeder Geld-/Mengenspalte in A und B, plus Anzahl unterschiedlicher Schlüssel. Eine Abweichung zeigt an, ob fehlende Zeilen, zusätzliche Zeilen oder Betragsdrift zu erwarten sind. Wenn Summen übereinstimmen, aber Zeilen abweichen, bedeutet dies sich ausgleichende Fehler; fahre fort.
  2. Schlüsselabgleich. Baue denselben normalisierten Schlüssel auf beiden Seiten (Abschnitt 3). Gleiche zuerst exakt ab, dann in expliziten Durchgängen mit abnehmender Strenge (z. B. nur Schlüssel, dann Schlüssel plus Zeitfenster), wobei jeder Treffer mit dem Durchgang markiert wird, der ihn erzeugt hat. Mische niemals Durchgänge ohne Markierung.
  3. Anti-Joins in beide Richtungen. A-nicht-in-B (fehlt in den abgeleiteten Daten) und B-nicht-in-A (unerwartet in den abgeleiteten Daten, oft OCR-Schlüsseltippfehler oder Duplikate). Melde beide; das Lesen nur einer Richtung verbirgt die Hälfte der Fehler. Bevor du eine Zeile als fehlend bezeichnest, überprüfe, ob ihr Schlüssel mit Duplikaten auf einer der Seiten kollidiert (Viele-zu-Viele-Joins erhöhen die Summen).
  4. Feldvergleich bei gepaarten Treffern. Vergleiche pro Feld nach derselben Normalisierung. Geldtoleranz: Vergleiche in Untereinheiten, abs(a - b) <= tol, wobei tol im Voraus festgelegt wird (0 für Hauptbücher; eine Rundungstoleranz wie 1 Untereinheit pro Zeile nur, wenn die Quellen unterschiedlich runden, und niemals ein Prozentsatz bei kleinen Beträgen). Daten: Exakt oder ein angegebenes Tagesfenster. Text: Normalisierte Gleichheit, dann ein Ähnlichkeitsscore, der als Score gemeldet wird, nicht als bestanden/nicht bestanden.
  5. Klassifiziere, unterscheide nicht nur. Jede Ausnahme erhält einen Grundcode: MISSING_IN_B, EXTRA_IN_B, DUP_KEY_A, DUP_KEY_B, AMOUNT_MISMATCH, FIELD_MISMATCH, UNPARSEABLE_A, UNPARSEABLE_B, AMBIGUOUS_MATCH. Nicht-parsbare Zeilen sind Ausnahmen und werden niemals stillschweigend von Summen ausgeschlossen.
  6. Schließe den Kreislauf. Die endgültige Identität muss gelten: |A| = matched + missing_in_B + dup_excess_A + unparseable_A (und das Pendant für B). Wenn sie nicht aufgeht, ist das Audit nicht abgeschlossen.

SQL-Muster für Durchgänge, Anti-Joins, Toleranz und die Saldenprüfung befinden sich in references/reconciliation-recipes.md.

Ausnahmebericht

Eine Zeile pro Ausnahme, lesbar ohne das Tooling: reason_code, key, A-Quelldatei und Zeilennummer, B-Quelldatei und Zeilennummer (und Seite bei gescannten Dokumenten), field, a_value, b_value, delta, suggested_action. Sortiere absteigend nach monetärer Auswirkung, dann nach Grund. Stelle eine Zusammenfassung voran: Eingaben mit Zeilenanzahlen und Prüfsummen, jeder Bereinigungsschritt mit Zählungen, Kontrollsummen beider Seiten, die Saldenidentität, verwendete Toleranzen. Schreibe CSV für die Maschine und eine kurze Markdown- oder XLSX-Ansicht für den Menschen; gib nicht Tausende von Zeilen in den Chat aus, fasse die Anzahl nach Grund zusammen und zeige die wichtigsten Beispiele.

Absicherungen

  • Überprüfe, schätze nicht: Zeilenanzahlen nach Joins, Schlüsseleindeutigkeit nach Deduplizierung, keine Float-Spalten für Geldbeträge.
  • Left Joins auf nicht-eindeutigen Schlüsseln multiplizieren Zeilen; überprüfe die Anzahl vor und nach jedem Join.
  • Überschreibe A nicht. Korrekturen an der Quelle der Wahrheit sind eine menschliche Entscheidung, die im Bericht aufgeführt wird.
  • Datenbankgeheimnisse werden aus /run/secrets/<name> gelesen, nicht aus Umgebungsvariablen oder der Kommandozeile.
  • Deklarative Prüfungen (soda-core, great_expectations) sind sinnvoll, sobald die Regeln stabil sind; das Profil und die Zählungen oben kommen zuerst.

Lessons learned aus der Praxis sammeln sich in references/gotchas.md.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Verwandte Skills