Skip to content

Commit f759b7f

Browse files
Merge pull request #180 from WilliamK112/agent/great-expectations-recipe
docs: add Great Expectations validation recipe
2 parents 1e0792f + 54e98ac commit f759b7f

4 files changed

Lines changed: 129 additions & 3 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ adheres to [Semantic Versioning](https://semver.org/).
99
### Added
1010
- Added a runnable PyJanitor interoperability example that demonstrates both
1111
tool orderings while keeping PyJanitor optional.
12+
- A dependency-optional Great Expectations recipe demonstrating the
13+
repair-then-validate workflow with an in-memory checkpoint.
1214

1315
## [2.0.0] - 2026-07-20
1416

‎docs/examples.md‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ directory has narrated Jupyter walkthroughs.
2222
| `05_ml_pipeline.py` | End-to-end ML preprocessing with scikit-learn |
2323
| `06_large_dataset.py` | Cleaning a large synthetic dataset, with timing |
2424
| `07_pandas_integration.py` | Dropping freshdata into an existing pandas workflow |
25-
| `08_csv_automation.py` | Batch CSV cleaning automation with audit logs |
2625
| `09_pandera_recipe.py` | Validating with pandera before and after freshdata cleaning |
2726
| `10_pyjanitor_interop.py` | Combining PyJanitor transforms with FreshData quality repair |
27+
| `11_great_expectations_recipe.py` | Repair string-typed data, then run an optional Great Expectations checkpoint |
2828

2929
## Missing-value cleaning
3030

@@ -97,3 +97,20 @@ install the compatible PyJanitor 0.31 line to run the example:
9797
pip install "pyjanitor<0.32"
9898
python examples/10_pyjanitor_interop.py
9999
```
100+
101+
## Great Expectations: repair, then validate
102+
103+
FreshData and Great Expectations have complementary roles: FreshData repairs
104+
representational problems and records the changes, while Great Expectations
105+
checks the result against an explicit data contract. Great Expectations remains
106+
an optional dependency:
107+
108+
```bash
109+
pip install great-expectations
110+
python examples/11_great_expectations_recipe.py
111+
```
112+
113+
The recipe runs the same checkpoint before and after `fd.clean()`. The raw
114+
currency and boolean strings fail the typed contract; after FreshData converts
115+
them to `float64` and `bool`, the checkpoint passes. The checkpoint validates
116+
the result but does not modify the DataFrame.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"""Repair a DataFrame with freshdata, then validate it with GX Core.
2+
3+
Great Expectations is optional and remains separate from freshdata's core
4+
dependencies. Install it before running this recipe:
5+
6+
pip install great-expectations
7+
python examples/11_great_expectations_recipe.py
8+
"""
9+
10+
import os
11+
12+
import pandas as pd
13+
14+
import freshdata as fd
15+
16+
os.environ.setdefault("GX_ANALYTICS_ENABLED", "false")
17+
18+
import great_expectations as gx # noqa: E402
19+
20+
21+
def make_checkpoint():
22+
"""Build an in-memory checkpoint for the cleaned orders contract."""
23+
context = gx.get_context(mode="ephemeral")
24+
context.variables.progress_bars = {
25+
"globally": False,
26+
"metric_calculations": False,
27+
}
28+
data_source = context.data_sources.add_pandas(name="freshdata_recipe")
29+
data_asset = data_source.add_dataframe_asset(name="orders")
30+
batch_definition = data_asset.add_batch_definition_whole_dataframe("whole_frame")
31+
32+
suite = context.suites.add(gx.ExpectationSuite(name="clean_orders"))
33+
suite.add_expectation(
34+
gx.expectations.ExpectColumnValuesToBeOfType(
35+
column="order_amount",
36+
type_="float64",
37+
)
38+
)
39+
suite.add_expectation(
40+
gx.expectations.ExpectColumnValuesToBeOfType(
41+
column="active",
42+
type_="bool",
43+
)
44+
)
45+
suite.add_expectation(
46+
gx.expectations.ExpectColumnValuesToBeBetween(
47+
column="order_amount",
48+
min_value=0,
49+
)
50+
)
51+
52+
validation_definition = context.validation_definitions.add(
53+
gx.ValidationDefinition(
54+
name="clean_orders_validation",
55+
data=batch_definition,
56+
suite=suite,
57+
)
58+
)
59+
return context.checkpoints.add(
60+
gx.Checkpoint(
61+
name="clean_orders_checkpoint",
62+
validation_definitions=[validation_definition],
63+
)
64+
)
65+
66+
67+
def validate(checkpoint, frame: pd.DataFrame) -> bool:
68+
"""Run the checkpoint against one in-memory DataFrame."""
69+
result = checkpoint.run(batch_parameters={"dataframe": frame})
70+
return bool(result.success)
71+
72+
73+
def main() -> None:
74+
raw = pd.DataFrame(
75+
{
76+
"customer_id": [1, 2, 3, 4, 5],
77+
"order_amount": ["$19.99", "$5.00", "$8.25", "$12.40", "$7.10"],
78+
"active": ["true", "false", "true", "true", "false"],
79+
}
80+
)
81+
checkpoint = make_checkpoint()
82+
83+
before = validate(checkpoint, raw)
84+
print(f"Before freshdata: checkpoint passed = {before}")
85+
86+
cleaned, report = fd.clean(
87+
raw,
88+
id_columns=("customer_id",),
89+
return_report=True,
90+
)
91+
after = validate(checkpoint, cleaned)
92+
93+
print(f"After freshdata: checkpoint passed = {after}")
94+
print(report.summary())
95+
96+
assert not before, "the raw string values should fail the typed contract"
97+
assert after, "the freshdata-cleaned values should pass the checkpoint"
98+
99+
100+
if __name__ == "__main__":
101+
main()

‎examples/README.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ python examples/01_missing_values.py
2121
| [`08_csv_automation.py`](08_csv_automation.py) | Batch CSV cleaning automation with audit logs |
2222
| [`09_pandera_recipe.py`](09_pandera_recipe.py) | Validating with pandera before and after freshdata cleaning |
2323
| [`10_pyjanitor_interop.py`](10_pyjanitor_interop.py) | Combining explicit PyJanitor transforms with FreshData quality repair |
24+
| [`11_great_expectations_recipe.py`](11_great_expectations_recipe.py) | Repairing with freshdata, then validating through a Great Expectations checkpoint |
2425

25-
The PyJanitor example has one optional dependency. FreshData 2.0 supports
26-
pandas 1.5–2.x, so install the compatible PyJanitor 0.31 line before running it:
26+
The PyJanitor and Great Expectations examples have optional dependencies.
27+
Install them only when running the corresponding example:
2728

2829
```bash
30+
# PyJanitor example (pandas 1.5–2.x compatible line)
2931
pip install "pyjanitor<0.32"
3032
python examples/10_pyjanitor_interop.py
33+
34+
# Great Expectations recipe
35+
pip install great-expectations
36+
python examples/11_great_expectations_recipe.py
3137
```
3238

3339
See the [documentation](https://freshcode-org.github.io/freshdata/) for full guides.

0 commit comments

Comments
 (0)