A small Polars-based toolkit for comparing two versions of a dataframe and generating randomized test data to exercise that comparison.
Project description
diffolars
A small Polars-based toolkit for comparing two versions of a dataframe and generating randomized test data to exercise that comparison.
Ideally used to compare dataloads in the day-to-day of a database analyst.
GitHub: https://github.com/ko222uky/diffolars
Installation
uv add diffolars
Generating test data
diffolars.demo generates a random dataframe and a mutated copy of it, useful
for testing diff logic without hand-crafting fixtures.
from diffolars.demo import get_df_pair
pair = get_df_pair(
n_rows=100,
n_cols=10,
n_new_rows=5, # rows added in the mutated copy
n_new_cols=2, # columns added in the mutated copy
coverage=0.1, # fraction of existing cells randomly changed
seed=42,
)
original = pair["original"]
mutated = pair["mutated"]
Every generated row gets a record_id UUID column, used to match rows
between the original and mutated dataframes. get_random_data and
get_mutated_data are also available individually if you want to generate or
mutate a dataframe on its own.
Diffing
diffolars.diff provides the comparison API for two dataloads (e.g. a
previous load vs. the latest load), and is under active development.
Inputs to these functions can be a list, polars.DataFrame, or
polars.LazyFrame.
column_intercept/column_symmetric_diff— shared vs. exclusive columns between the two tablesrow_intercept/row_symmetric_diff— shared vs. exclusive rows, based on a record ID columnprune_rows— returns the rows exclusive to each table (i.e. dropped by the join), tagged with which table they came fromreport_prune— summarizes the pruned rows/columns as a single dict entry, suitable for loggingget_core— prunes each table down to their shared rows and columns, and returns them as a pair of_A/_B-suffixed DataFrames ready for a field-to-field comparisonbitdiff— joins the two core tables and computes a per-rowdiff_bitarray(pl.UInt64), with each bit flagging whether a given column matched between the previous and latest loadbitdiff_summary— reads back abitdiffresult and reports, per core column, how many rows were modified vs. not modifiedbitarray_upset_plot/bitdiff_plot— builds an upset plot (matplotlib) showing which columns tend to be modified together, with an optionaltop_nto limit the plot to the most-frequently-modified columns and a left-hand histogram of each column's total modification count
Currently only the Windows build is available.
Command-line interface
diffolars.cli exposes diff_cli, a Click command that runs the diff
pipeline (report_prune, pruned_rows, bitdiff) over two parquet dataloads
and prints the three result tables. It's registered as the diffolars
console script.
From within this project:
uv run diffolars \
--prev-load original.parquet \
--latest-load mutated.parquet \
--id-col record_id
Or by using uvx:
uvx diffolars \
--prev-load original.parquet \
--latest-load mutated.parquet \
--id-col record_id
| Option | Default | Description |
|---|---|---|
--prev-load |
original.parquet |
Path to the previous/original data load. |
--latest-load |
mutated.parquet |
Path to the latest/mutated data load. |
--id-col |
record_id |
Name of the record identifier column. |
--scan / --no-scan |
--scan |
Read with pl.scan_parquet (lazy) instead of pl.read_parquet (eager). |
--write / --no-write |
--write |
Write the resulting diff tables to parquet. |
--bitarray-summary / --no-bitarray-summary |
--bitarray-summary |
Produce a per-column modified/not-modified summary and upset plot after the bitdiff is computed. |
--top-n |
20 |
Limit the upset plot to the top N most-frequently-modified columns. |
When --write is set (the default), results are saved under
data/<prev-stem>-<latest-stem>/<today's date>/, as
diff_activity_log_record.parquet, diff_record_differences.parquet, and
diff_bitarray_results.parquet. If --bitarray-summary is also set, this
directory additionally gets bitarray_summary.parquet and
bitarray_summary_upsetplot.png.
API reference
Static API docs are generated with pdoc from the package's docstrings, and are hosted at ko222uky.github.io/diffolars (source lives under docs/api). Regenerate them after docstring changes with:
uv run --group dev pdoc diffolars -o docs/api
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file diffolars-1.0.1.tar.gz.
File metadata
- Download URL: diffolars-1.0.1.tar.gz
- Upload date:
- Size: 13.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
beda4461380fca1d1dc8343edf1a93c5c868e06963248d4ffad35fd4571139d2
|
|
| MD5 |
94043ad6b08167e37011986f124d0ef6
|
|
| BLAKE2b-256 |
632ee17b6185674c2b80a6e60e5aee695eb3db4f035f6d462e988bd140c72281
|
File details
Details for the file diffolars-1.0.1-py3-none-any.whl.
File metadata
- Download URL: diffolars-1.0.1-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea9c2ffcabe319ec090d1de19df517fe410cc6e243f16c07dac2be5bc13b6409
|
|
| MD5 |
25a2b7be2385dd833f1487765c0cd7c9
|
|
| BLAKE2b-256 |
2d8700a76bcda53798f2202b693b6aa1d858803c1f0af6b7891983046df0b04b
|