Skip to content

Commit 7d69bea

Browse files
committed
📝 Update the section on data cleaning
* Add validation categories and procedures * Add text encoding with charset_normalizer and ftfy * Add DataProfiler and cerberus
1 parent 78b8263 commit 7d69bea

34 files changed

Lines changed: 1956 additions & 965 deletions

‎CHANGELOG.rst‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ emergencies when we need to start branches for older versions.
2323
Added
2424
~~~~~
2525

26+
* 📝 Update the section on data cleaning
27+
28+
* Add validation categories and procedures
29+
* Add text encoding with charset_normalizer and ftfy
30+
* Add DataProfiler and cerberus
31+
2632
* 📝 Add Narwhals
2733
* 📝 Add protobuf-py
2834

‎docs/clean-prep/categories.rst‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
.. SPDX-FileCopyrightText: 2026 cusy GmbH
2+
..
3+
.. SPDX-License-Identifier: BSD-3-Clause
4+
5+
Categories of data quality
6+
==========================
7+
8+
There are various ways to categorise data quality issues – by the cause of the
9+
problem, by its likely or potential impact, by the type of data element, or by
10+
the level of a data hierarchy at which the error or inconsistency becomes
11+
apparent, to name but a few. In this tutorial, categorisation is generally
12+
implicit, and we focus on the methods for detecting problems and the tools
13+
suitable for this purpose. However, it is useful to at least briefly touch upon
14+
other ways of categorising data problems before we turn our attention to
15+
detection.
16+
17+
Impossible data
18+
such as temperatures below absolute zero (0 Kelvin or −273.15 °C) or
19+
nonsensical date and time values – whilst these cannot occur in the
20+
:class:`datetime` data type in Python, they can occur in
21+
:doc:`../data-processing/serialisation-formats/json/index` and :doc:`SQLite
22+
<python-basics:save-data/sqlite/index>`, where text fields are usually used
23+
to store date information.
24+
Special values
25+
The `IEEE-754 <https://en.wikipedia.org/wiki/IEEE_754>`_ standard for
26+
representing floating-point numbers also includes special values for
27+
positive and negative infinity (+∞, −∞) as well as *Not a Number* (``NaN``)
28+
values.
29+
Unspecified Values
30+
Values that conform to a specific format may nevertheless be invalid, such
31+
as email addresses.
32+
Inconsistencies
33+
Groups of related field values for each record may be mutually exclusive. To
34+
avoid such inconsistencies, the :abbr:`DRY (Don’t Repeat Yourself)`
35+
principle recommends disregarding calculable values. Checksums, however, are
36+
the exact opposite of this.
37+
38+
*‘Single Source of Truth’* is an example of database normalisation and
39+
simplifies updates; with denormalised data stores, on the other hand, joins
40+
and calculations can be avoided during data analysis.
41+
42+
Anomalies and data drift
43+
The checks carried out to date have made it possible to declare data
44+
invalid. However, anomalies and data drift do not necessarily support this
45+
conclusion and therefore rarely allow for automated data cleansing.
46+
Malware
47+
Not all input or output data should be processed in analysis systems.
48+
49+
.. figure:: exploits_of_a_mom_2x.png
50+
:alt: Hi, this is your son’s school. We’re having some computer trouble.
51+
Oh, dear - did he break something? In a way –
52+
Did you really name your son Robert'); DROP TABLE Students; -- ?
53+
Oh, yes. Little bobby tables, we call him.
54+
Well, weve lost this year’s student records. I hope you’re happy.
55+
And I hope, youe’ve learned to sanitize your database inpots.
56+
:target: https://xkcd.com/327/
57+
58+
Exploits of a Mom
59+
60+
Ein offensichtliches Beispiel für versehentlich offengelegte Ausgabedaten
61+
sind :abbr:`z. B. (zum Beispiel)` aus fortlaufenden Personenkennziffern
62+
generierte URLs mit personenbezogenen Daten.
65.9 KB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2026 cusy GmbH
2+
3+
SPDX-License-Identifier: BSD-3-Clause

‎docs/clean-prep/index.rst‎

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,67 +2,60 @@
22
..
33
.. SPDX-License-Identifier: BSD-3-Clause
44
5-
Data cleansing and validation
6-
=============================
5+
Cleaning and validating data
6+
============================
77

8-
In the following, we want to give you a practical overview of various libraries
9-
and methods for `data cleansing <https://en.wikipedia.org/wiki/Data_cleansing>`_
10-
and validation with Python. Besides well-known libraries like
11-
:doc:`/workspace/numpy/index` and ,:doc:`/workspace/pandas/index`
12-
we also use several small, specialised libraries like :doc:`dedupe
13-
<deduplicate>`, :doc:`fuzzywuzzy <string-matching>`, :doc:`voluptuous
14-
<voluptuous>`, :doc:`tdda <tdda>` and :doc:`hypothesis <hypothesis>`. We prefer
15-
these more lightweight solutions to large, universal systems like `Great
16-
Expectations <https://greatexpectations.io/>`_ or `MobyDQ
17-
<https://ubisoft.github.io/mobydq/>`_.
8+
*‘Garbage in, garbage out’* is a stark reminder that it is almost impossible to
9+
draw meaningful insights from poor-quality data. Whilst there are highly
10+
regulated, safety-critical sectors in which data is routinely checked at every
11+
stage, the general standard of data validation in most analytical projects tends
12+
to be rather low.
1813

19-
.. tip::
20-
`cusy seminar: Cleanse and validate data with Python
21-
<https://cusy.io/en/our-training-courses/cleanse-and-validate-data-with-python.html>`_
14+
However, if we write code to analyse data without first checking it, some
15+
results will be misleading, incorrect or invalid. The same applies if we fail to
16+
validate our output. In doing so, we end up contributing to the very *‘bad
17+
data’* that we all rail against. *Postel’s Law* – the principle of robustness
18+
proposed in the TCP standard – is helpful here:
19+
20+
*“be conservative in what you do, be liberal in what you accept from
21+
others.”* [#]_
22+
23+
This stands in stark contrast to one of Python’s principles:
2224

23-
Overview
24-
--------
25+
*“Errors should never pass silently.”* [#]_
2526

26-
.. csv-table:: GitHub-Insights
27-
:header: "Name", "Stars", "Mitwirkende", "Commit-Aktivität", "Lizenz"
27+
The :doc:`XML <../data-processing/serialisation-formats/xml-html/index>`
28+
specification also requires that malformed XML documents be rejected:
2829

29-
"`scikit-learn <https://github.com/scikit-learn/scikit-learn>`_",".. image:: https://raster.shields.io/github/stars/scikit-learn/scikit-learn",".. image:: https://raster.shields.io/github/contributors/scikit-learn/scikit-learn",".. image:: https://raster.shields.io/github/commit-activity/y/scikit-learn/scikit-learn",".. image:: https://raster.shields.io/github/license/scikit-learn/scikit-learn"
30-
"`fg-data-profiling <https://github.com/Data-Centric-AI-Community/fg-data-profiling>`_",".. image:: https://raster.shields.io/github/stars/Data-Centric-AI-Community/fg-data-profiling",".. image:: https://raster.shields.io/github/contributors/Data-Centric-AI-Community/fg-data-profiling",".. image:: https://raster.shields.io/github/commit-activity/y/Data-Centric-AI-Community/fg-data-profiling",".. image:: https://raster.shields.io/github/license/Data-Centric-AI-Community/fg-data-profiling"
31-
"`Hypothesis <https://github.com/HypothesisWorks/hypothesis>`_",".. image:: https://raster.shields.io/github/stars/HypothesisWorks/hypothesis",".. image:: https://raster.shields.io/github/contributors/HypothesisWorks/hypothesis",".. image:: https://raster.shields.io/github/commit-activity/y/HypothesisWorks/hypothesis",".. image:: https://raster.shields.io/github/license/HypothesisWorks/hypothesis"
32-
"`marshmallow <https://github.com/marshmallow-code/marshmallow>`_",".. image:: https://raster.shields.io/github/stars/marshmallow-code/marshmallow",".. image:: https://raster.shields.io/github/contributors/marshmallow-code/marshmallow",".. image:: https://raster.shields.io/github/commit-activity/y/marshmallow-code/marshmallow",".. image:: https://raster.shields.io/github/license/marshmallow-code/marshmallow"
33-
"`dedupe <https://github.com/dedupeio/dedupe>`_",".. image:: https://raster.shields.io/github/stars/dedupeio/dedupe",".. image:: https://raster.shields.io/github/contributors/dedupeio/dedupe",".. image:: https://raster.shields.io/github/commit-activity/y/dedupeio/dedupe",".. image:: https://raster.shields.io/github/license/dedupeio/dedupe"
34-
"`pandera <https://github.com/unionai-oss/pandera>`_",".. image:: https://raster.shields.io/github/stars/unionai-oss/pandera",".. image:: https://raster.shields.io/github/contributors/unionai-oss/pandera",".. image:: https://raster.shields.io/github/commit-activity/y/unionai-oss/pandera",".. image:: https://raster.shields.io/github/license/unionai-oss/pandera"
35-
"`thefuzz <https://github.com/seatgeek/thefuzz>`_",".. image:: https://raster.shields.io/github/stars/seatgeek/thefuzz",".. image:: https://raster.shields.io/github/contributors/seatgeek/thefuzz",".. image:: https://raster.shields.io/github/commit-activity/y/seatgeek/thefuzz",".. image:: https://raster.shields.io/github/license/seatgeek/thefuzz"
36-
"`Voluptuous <https://github.com/alecthomas/voluptuous>`_",".. image:: https://raster.shields.io/github/stars/alecthomas/voluptuous",".. image:: https://raster.shields.io/github/contributors/alecthomas/voluptuous",".. image:: https://raster.shields.io/github/commit-activity/y/alecthomas/voluptuous",".. image:: https://raster.shields.io/github/license/alecthomas/voluptuous"
37-
"`datacleaner <https://github.com/rhiever/datacleaner>`_",".. image:: https://raster.shields.io/github/stars/rhiever/datacleaner",".. image:: https://raster.shields.io/github/contributors/rhiever/datacleaner",".. image:: https://raster.shields.io/github/commit-activity/y/rhiever/datacleaner",".. image:: https://raster.shields.io/github/license/rhiever/datacleaner"
38-
"`popmon <https://github.com/ing-bank/popmon>`_",".. image:: https://raster.shields.io/github/stars/ing-bank/popmon",".. image:: https://raster.shields.io/github/contributors/ing-bank/popmon",".. image:: https://raster.shields.io/github/commit-activity/y/ing-bank/popmon",".. image:: https://raster.shields.io/github/license/ing-bank/popmon"
39-
"`TDDA <https://github.com/tdda/tdda>`_",".. image:: https://raster.shields.io/github/stars/tdda/tdda",".. image:: https://raster.shields.io/github/contributors/tdda/tdda",".. image:: https://raster.shields.io/github/commit-activity/y/tdda/tdda",".. image:: https://raster.shields.io/github/license/tdda/tdda"
40-
"`Validr <https://github.com/guyskk/validr>`_",".. image:: https://raster.shields.io/github/stars/guyskk/validr",".. image:: https://raster.shields.io/github/contributors/guyskk/validr",".. image:: https://raster.shields.io/github/commit-activity/y/guyskk/validr",".. image:: https://raster.shields.io/github/license/guyskk/validr"
41-
"`Probatus <https://github.com/ing-bank/probatus>`_",".. image:: https://raster.shields.io/github/stars/ing-bank/probatus",".. image:: https://raster.shields.io/github/contributors/ing-bank/probatus",".. image:: https://raster.shields.io/github/commit-activity/y/ing-bank/probatus",".. image:: https://raster.shields.io/github/license/ing-bank/probatus"
30+
“„Validating and non-validating processors alike MUST report violations of
31+
this specification's well-formedness constraints … that they read.”* [#]_
4232

43-
Dormant projects
44-
----------------
33+
The sections on :doc:`procedures/index`, :doc:`procedures/ranges` and
34+
:doc:`procedures/regression_tests` do not require any prior knowledge of Python
35+
and are therefore generally suitable for professionals in the fields of data
36+
management, business management and quality assurance.
37+
38+
We will then provide you with a practical overview of various :doc:`libraries
39+
and methods <libs-methods/index>` for `data cleaning
40+
<https://en.wikipedia.org/wiki/Data_cleansing>`_ and validation using Python.
41+
42+
.. tip::
43+
`cusy seminar: Cleanse and validate data with Python
44+
<https://cusy.io/en/our-training-courses/cleanse-and-validate-data-with-python.html>`_
4545

46-
.. csv-table:: GitHub-Insights
47-
:header: "Name", "Stars", "Mitwirkende", "Commit-Aktivität", "Lizenz"
46+
----
4847

49-
"`Bulwark <https://github.com/ZaxR/bulwark>`_",".. image:: https://raster.shields.io/github/stars/ZaxR/bulwark",".. image:: https://raster.shields.io/github/contributors/ZaxR/bulwark",".. image:: https://raster.shields.io/github/commit-activity/y/ZaxR/bulwark",".. image:: https://raster.shields.io/github/license/ZaxR/bulwark"
50-
"`PandasSchema <https://github.com/multimeric/PandasSchema>`_",".. image:: https://raster.shields.io/github/stars/multimeric/PandasSchema",".. image:: https://raster.shields.io/github/contributors/multimeric/PandasSchema",".. image:: https://raster.shields.io/github/commit-activity/y/multimeric/PandasSchema",".. image:: https://raster.shields.io/github/license/multimeric/PandasSchema"
51-
"`pandas-validation <https://github.com/jmenglund/pandas-validation>`_",".. image:: https://raster.shields.io/github/stars/jmenglund/pandas-validation",".. image:: https://raster.shields.io/github/contributors/jmenglund/pandas-validation",".. image:: https://raster.shields.io/github/commit-activity/y/jmenglund/pandas-validation",".. image:: https://raster.shields.io/github/license/jmenglund/pandas-validation"
52-
"`Opulent-Pandas <https://github.com/danielvdende/opulent-pandas>`_",".. image:: https://raster.shields.io/github/stars/danielvdende/opulent-pandas",".. image:: https://raster.shields.io/github/contributors/danielvdende/opulent-pandas",".. image:: https://raster.shields.io/github/commit-activity/y/danielvdende/opulent-pandas",".. image:: https://raster.shields.io/github/license/danielvdende/opulent-pandas"
53-
"`signpost <https://github.com/ilsedippenaar/signpost>`_",".. image:: https://raster.shields.io/github/stars/ilsedippenaar/signpost",".. image:: https://raster.shields.io/github/contributors/ilsedippenaar/signpost",".. image:: https://raster.shields.io/github/commit-activity/y/ilsedippenaar/signpost",".. image:: https://raster.shields.io/github/license/ilsedippenaar/signpost"
48+
.. [#] Jon Postel: `Transmission Control Protocol
49+
<https://www.rfc-editor.org/info/rfc761/#section-2.10>`_, 1980
50+
.. [#] Tim Peters: :pep:`The Zen of Python <20>`, 1999
51+
.. [#] `XML Specification 1.0, Section 5.1
52+
<https://www.w3.org/TR/2008/REC-xml-20081126/#proc-types>`_, 1998
5453
5554
.. toctree::
5655
:hidden:
5756
:titlesonly:
5857
:maxdepth: 0
5958

60-
nulls.ipynb
61-
outliers.ipynb
62-
string-matching.ipynb
63-
deduplicate.ipynb
64-
hypothesis.ipynb
65-
tdda.ipynb
66-
voluptuous.ipynb
67-
scikit-learn-reprocessing.ipynb
68-
dask-pipeline.ipynb
59+
categories
60+
procedures/index
61+
libs-methods/index

docs/clean-prep/dask-pipeline.ipynb renamed to docs/clean-prep/libs-methods/dask-pipeline.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"1. [Google Maps Geocoder](https://developers.google.com/maps/documentation/geocoding/guides-v3/overview)\n",
1919
"2. [Open Notify API for ISS location](http://api.open-notify.org)\n",
2020
"\n",
21-
"We will use them to track ISS location and next transit time with respect to a list of cities. To create our charts and parallelise data intelligently, we will use Dask, specifically [Dask Delayed](../performance/dask.ipynb)."
21+
"We will use them to track ISS location and next transit time with respect to a list of cities. To create our charts and parallelise data intelligently, we will use Dask, specifically [Dask Delayed](../../performance/dask.ipynb)."
2222
]
2323
},
2424
{
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)