A practical reference for profiling and validating new data sources before transformation.
You should not clean data because it looks ugly. Establish what "correct" means, then test whether the data meets that expectation.
SOURCE
↓
RAW / LANDING
↓
PROFILE
↓
UNDERSTAND
↓
DEFINE EXPECTATIONS
↓
QUALITY CHECKS
↓
TRANSFORM
↓
TRUSTED DATA
- Can I read the source?
- Did the expected data arrive?
- What is the schema?
- What does one row represent? (grain)
- How many rows arrived?
- Which fields are missing?
- Which fields should be unique?
- Which values are valid?
- Which numerical ranges are valid?
- Do relationships between tables make sense?
- Do dates/timestamps make sense?
- Does the distribution look normal?
- Does today's data make sense compared with historical data?
A duplicate is only a problem when it violates the expected grain.
members: one row = one member →member_idshould usually be unique.payments: one row = one payment →payment_idshould usually be unique, butmember_idcan repeat.checkins: one row = one gym visit →member_idis expected to repeat.
dbt/data_quality.yml— warehouse/dbt test reference.python/data_quality_checks.py— reusable pandas checks.
Can the source be read? Is the schema what we expect?
Are required values present?
Are identifiers unique at the correct grain?
Are values within accepted sets or ranges?
Do relationships between tables point to real records?
Do fields agree with each other?
Example:
signup_date <= payment_date
Did data arrive when expected?
Did roughly the expected amount of data arrive?
Does today's data behave unusually compared with history?
Not every unusual value is bad data.
A NULL email may be acceptable if email is optional.
A negative account balance may be legitimate.
A duplicate member_id is expected in a check-in table.
The business meaning determines the rule.
OBSERVE
↓
UNDERSTAND
↓
DEFINE EXPECTATIONS
↓
VALIDATE
↓
TRANSFORM
That is the mindset this repository is meant to reinforce.