diff --git a/diffly/cli.py b/diffly/cli.py index d3560eb..7177e58 100644 --- a/diffly/cli.py +++ b/diffly/cli.py @@ -12,10 +12,18 @@ from ._compat import typer from ._utils import ABS_TOL_DEFAULT, ABS_TOL_TEMPORAL_DEFAULT, REL_TOL_DEFAULT -from .metrics import DEFAULT_METRICS +from .metrics import Metric, MetricFn +from .metrics.change import DEFAULT_CHANGE_METRICS +from .metrics.data import DEFAULT_DATA_METRICS app = typer.Typer() +#: All metric presets selectable via ``--metric``, combining the change and data sets. +AVAILABLE_METRICS: dict[str, MetricFn | Metric] = { + **DEFAULT_CHANGE_METRICS, + **DEFAULT_DATA_METRICS, +} + @app.command() def main( @@ -139,8 +147,8 @@ def main( list[str], typer.Option( help=( - "Metric presets to display per numerical column. Repeatable. " - f"Available: {', '.join(DEFAULT_METRICS)}." + "Metric presets to display per column. Repeatable. " + f"Available: {', '.join(AVAILABLE_METRICS)}." ) ), ] = [], @@ -154,11 +162,11 @@ def main( hidden_column = [*hidden_column, *hidden_columns] for name in metric: - if name not in DEFAULT_METRICS: + if name not in AVAILABLE_METRICS: raise typer.BadParameter( - f"Unknown metric: {name!r}. Available: {', '.join(DEFAULT_METRICS)}." + f"Unknown metric: {name!r}. Available: {', '.join(AVAILABLE_METRICS)}." ) - metrics = {name: DEFAULT_METRICS[name] for name in metric} + metrics = {name: AVAILABLE_METRICS[name] for name in metric} comparison = compare_frames( pl.scan_parquet(left), diff --git a/diffly/comparison.py b/diffly/comparison.py index 786c4c2..6976b9c 100644 --- a/diffly/comparison.py +++ b/diffly/comparison.py @@ -25,7 +25,7 @@ lazy_len, make_and_validate_mapping, ) -from .metrics import MetricFn, _make_numeric_metric +from .metrics import Metric, MetricFn, _make_numeric_metric if TYPE_CHECKING: # pragma: no cover # NOTE: We cannot import at runtime as we're otherwise running into circular @@ -920,7 +920,7 @@ def summary( right_name: str = Side.RIGHT, slim: bool = False, hidden_columns: list[str] | None = None, - metrics: Mapping[str, MetricFn] | None = None, + metrics: Mapping[str, MetricFn | Metric] | None = None, ) -> Summary: """Generate a summary of all aspects of the comparison. @@ -950,16 +950,18 @@ def summary( advanced users who are familiar with the summary format. hidden_columns: Columns for which no values are printed, e.g. because they contain sensitive information. - metrics: Optional mapping from display label to a metric callable - ``(left_expr, right_expr) -> pl.Expr``. Each callable receives two + metrics: Optional mapping from display label to a metric. A value may be a + callable ``(left_expr, right_expr) -> pl.Expr`` or a + :class:`~diffly.metrics.Metric`. Each callable receives two :class:`polars.Expr` referring to the left and right values of a single - numerical column across all joined rows, and must return a scalar - aggregation expression. See :doc:`/api/metrics` for the full list of - presets and the :data:`~diffly.metrics.MetricFn` type. When ``None`` - (default), no metrics are computed; presets are not applied - automatically. Metrics are only computed for numerical columns. Prefer - short labels — the summary has a fixed width and many or long labels - degrade rendering. + column across all joined rows, and must return a scalar aggregation + expression. Bare callables are only computed for numerical columns; wrap + one in a :class:`~diffly.metrics.Metric` with a column selector to target + other column types (e.g. ``Metric(fn, selector=cs.all())``). + See :doc:`/api/metrics` for the full list of presets and the + :data:`~diffly.metrics.MetricFn` type. When ``None`` (default), no metrics + are computed; presets are not applied automatically. Prefer short labels — + the summary has a fixed width and many or long labels degrade rendering. Returns: A summary which can be printed or written to a file. @@ -976,7 +978,10 @@ def summary( from .summary import Summary resolved_metrics = ( - {label: _make_numeric_metric(fn) for label, fn in metrics.items()} + { + label: v if isinstance(v, Metric) else _make_numeric_metric(v) + for label, v in metrics.items() + } if metrics is not None else None ) diff --git a/diffly/metrics/__init__.py b/diffly/metrics/__init__.py new file mode 100644 index 0000000..a3a165b --- /dev/null +++ b/diffly/metrics/__init__.py @@ -0,0 +1,50 @@ +# Copyright (c) QuantCo 2025-2026 +# SPDX-License-Identifier: BSD-3-Clause + +"""Metrics computed per column when generating a summary. + +Two families are provided: + +- Metrics in :mod:`~diffly.metrics.change` describe the change between numeric + columns itself by aggregating over ``right - left``. +- Metrics in :mod:`~diffly.metrics.data` describe the left and right datasets + individually, explaining how a change affects the data. +""" + +from __future__ import annotations + +from . import change, data +from ._common import Metric, MetricFn +from .change import ( + _make_numeric_metric, + max, + mean, + mean_absolute_deviation, + mean_relative_deviation, + median, + min, + quantile, + std, +) + +DEFAULT_METRICS: dict[str, MetricFn | Metric] = { + **change.DEFAULT_CHANGE_METRICS, +} +"""The default preset metrics, consisting of the change default set.""" + +__all__ = [ + "DEFAULT_METRICS", + "Metric", + "MetricFn", + "change", + "data", + "max", + "mean", + "mean_absolute_deviation", + "mean_relative_deviation", + "median", + "min", + "quantile", + "std", + "_make_numeric_metric", +] diff --git a/diffly/metrics/_common.py b/diffly/metrics/_common.py new file mode 100644 index 0000000..5ba7c38 --- /dev/null +++ b/diffly/metrics/_common.py @@ -0,0 +1,27 @@ +# Copyright (c) QuantCo 2025-2026 +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass + +import polars as pl +import polars.selectors as cs + + +@dataclass(frozen=True) +class Metric: + """A metric function paired with a column-applicability selector.""" + + fn: MetricFn + selector: cs.Selector + + +MetricFn = Callable[[pl.Expr, pl.Expr], pl.Expr] +"""A metric function maps ``(left_expr, right_expr)`` to a scalar aggregation +expression. + +The expressions refer to the left-side and right-side values of a single column across +all joined rows. +""" diff --git a/diffly/metrics.py b/diffly/metrics/change.py similarity index 77% rename from diffly/metrics.py rename to diffly/metrics/change.py index 075536e..f4965f1 100644 --- a/diffly/metrics.py +++ b/diffly/metrics/change.py @@ -1,33 +1,17 @@ # Copyright (c) QuantCo 2025-2026 # SPDX-License-Identifier: BSD-3-Clause -from __future__ import annotations +"""Metrics describing the change between numeric columns. + +These aggregate over ``right - left`` to characterize the change itself. +""" -from collections.abc import Callable -from dataclasses import dataclass +from __future__ import annotations import polars as pl import polars.selectors as cs - -@dataclass(frozen=True) -class Metric: - """A metric function paired with a column-applicability selector. - - Internal only. - """ - - fn: MetricFn - selector: cs.Selector - - -MetricFn = Callable[[pl.Expr, pl.Expr], pl.Expr] -"""A metric function maps ``(left_expr, right_expr)`` to a scalar aggregation -expression. - -The expressions refer to the left-side and right-side values of a single column across -all joined rows. -""" +from ._common import Metric, MetricFn def _make_numeric_metric(fn: MetricFn) -> Metric: @@ -82,7 +66,7 @@ def _quantile(left: pl.Expr, right: pl.Expr) -> pl.Expr: return _quantile -DEFAULT_METRICS: dict[str, MetricFn] = { +DEFAULT_CHANGE_METRICS: dict[str, MetricFn] = { "Mean": mean, "Median": median, "Min": min, @@ -91,3 +75,4 @@ def _quantile(left: pl.Expr, right: pl.Expr) -> pl.Expr: "Mean absolute deviation": mean_absolute_deviation, "Mean relative deviation": mean_relative_deviation, } +"""Preset metrics describing the change between numeric columns.""" diff --git a/diffly/metrics/data.py b/diffly/metrics/data.py new file mode 100644 index 0000000..066a06b --- /dev/null +++ b/diffly/metrics/data.py @@ -0,0 +1,75 @@ +# Copyright (c) QuantCo 2025-2026 +# SPDX-License-Identifier: BSD-3-Clause + +"""Metrics describing the left and right datasets individually. + +These characterize each side of a change so you can understand how the change affects +the data, rather than describing the change itself. +""" + +from __future__ import annotations + +from collections.abc import Callable + +import polars as pl +import polars.selectors as cs + +from ._common import Metric, MetricFn + + +def null_fraction_change(left: pl.Expr, right: pl.Expr) -> pl.Expr: + """Change in the fraction of null entries, rendered as `` -> ()``. + + ``old`` and ``new`` are the null percentages of the left and right side, and + ``delta`` is their signed difference (``+`` when the right side has proportionally + more nulls, ``-`` when it has fewer). This metric function can be applied to columns + of any type. + """ + return _render_change( + left.is_null().mean(), + right.is_null().mean(), + lambda value, signed: _percentage_string( + value, signed=signed, percent_sign=not signed + ), + ) + + +DEFAULT_DATA_METRICS: dict[str, MetricFn | Metric] = { + "Null%": Metric(fn=null_fraction_change, selector=cs.all()), +} +"""Preset metrics describing the left and right datasets individually.""" + + +# ------------------------------------------------------------------------------------ # +# UTILITY METHODS # +# ------------------------------------------------------------------------------------ # + + +def _percentage_string( + fraction: pl.Expr, *, signed: bool = False, percent_sign: bool = True +) -> pl.Expr: + """Format a fraction as a percentage string, optionally with an explicit sign.""" + pct = (fraction * 100).round(2) + body = pl.format("{}%", pct) if percent_sign else pl.format("{}", pct) + if signed: + return pl.when(pct >= 0).then(pl.format("+{}", body)).otherwise(body) + return body + + +def _render_change( + old: pl.Expr, + new: pl.Expr, + format_value: Callable[[pl.Expr, bool], pl.Expr], +) -> pl.Expr: + """Render a change as `` -> ()``. + + ``format_value(value, signed)`` formats a value for display; ``old`` and ``new`` are + rendered unsigned and the delta ``new - old`` is rendered signed (with an explicit + ``+`` prefix for positive values). + """ + return pl.format( + "{} -> {} ({})", + format_value(old, False), + format_value(new, False), + format_value(new - old, True), + ) diff --git a/diffly/summary.py b/diffly/summary.py index 3edf645..ac3dda7 100644 --- a/diffly/summary.py +++ b/diffly/summary.py @@ -1131,10 +1131,13 @@ def _format_value(value: Any, *, float_format: str | None = None) -> str: def _format_metric_value(value: Any) -> str: """Format a metric value for the column summary. - Blanks out ``None`` and renders floats with ``.4g`` precision. + Blanks out ``None``, renders string values verbatim, and renders floats with ``.4g`` + precision. """ if value is None: return "" + if isinstance(value, str): + return _yellow(value) return _format_value(value, float_format=".4g") diff --git a/diffly/testing.py b/diffly/testing.py index 367a304..9a36458 100644 --- a/diffly/testing.py +++ b/diffly/testing.py @@ -19,7 +19,7 @@ from ._compat import dy from .comparison import DataFrameComparison, compare_frames -from .metrics import MetricFn +from .metrics import Metric, MetricFn def assert_collection_equal( @@ -40,7 +40,7 @@ def assert_collection_equal( right_name: str = Side.RIGHT, slim: bool = False, hidden_columns: list[str] | None = None, - metrics: Mapping[str, MetricFn] | None = None, + metrics: Mapping[str, MetricFn | Metric] | None = None, ) -> None: """Assert that two :mod:`dataframely` collections are equal. @@ -85,9 +85,11 @@ def assert_collection_equal( hidden_columns: Columns for which no values are printed, e.g. because they contain sensitive information. metrics: Optional mapping from display label to a metric callable - ``(left_expr, right_expr) -> pl.Expr``. See :mod:`diffly.metrics` for - presets. When ``None`` (default), no metrics are computed; presets are - not applied automatically. + ``(left_expr, right_expr) -> pl.Expr`` or a :class:`~diffly.metrics.Metric`. + Bare callables are only computed for numerical columns; wrap one in a + :class:`~diffly.metrics.Metric` with a column selector to target other column + types. See :mod:`diffly.metrics` for presets. When ``None`` (default), no + metrics are computed; presets are not applied automatically. Raises: AssertionError: If the collections are not equal. @@ -174,7 +176,7 @@ def assert_frame_equal( right_name: str = Side.RIGHT, slim: bool = False, hidden_columns: list[str] | None = None, - metrics: Mapping[str, MetricFn] | None = None, + metrics: Mapping[str, MetricFn | Metric] | None = None, ) -> None: """Assert that two :mod:`polars` data frames are equal. @@ -226,9 +228,11 @@ def assert_frame_equal( hidden_columns: Columns for which no values are printed, e.g. because they contain sensitive information. metrics: Optional mapping from display label to a metric callable - ``(left_expr, right_expr) -> pl.Expr``. See :mod:`diffly.metrics` for - presets. When ``None`` (default), no metrics are computed; presets are - not applied automatically. + ``(left_expr, right_expr) -> pl.Expr`` or a :class:`~diffly.metrics.Metric`. + Bare callables are only computed for numerical columns; wrap one in a + :class:`~diffly.metrics.Metric` with a column selector to target other column + types. See :mod:`diffly.metrics` for presets. When ``None`` (default), no + metrics are computed; presets are not applied automatically. Raises: AssertionError: If the data frames are not equal. diff --git a/docs/api/metrics.rst b/docs/api/metrics.rst index 27df193..84c8f82 100644 --- a/docs/api/metrics.rst +++ b/docs/api/metrics.rst @@ -4,17 +4,41 @@ Metrics .. currentmodule:: diffly.metrics -Metrics are scalar aggregations computed per numerical column when generating a +Metrics are scalar aggregations computed per column when generating a :meth:`~diffly.comparison.DataFrameComparison.summary`. Pass them via the ``metrics`` argument as a mapping from display label to a :data:`MetricFn` callable. :mod:`diffly.metrics` ships a set of presets; you can also supply your own callable ``(left_expr, right_expr) -> pl.Expr``. +A bare callable is only computed for numerical columns. To target a different +set of columns, wrap it in a :class:`Metric` with a column selector, e.g. +``Metric(fn, selector=cs.all())``, ``Metric(fn, selector=cs.boolean())``, or +``Metric(fn, selector=cs.by_name("my_column_name"))``. + +Presets come in two families, each with its own module and default set: + +- :mod:`diffly.metrics.change` describes the *change* between numeric columns by + aggregating over ``right - left``. +- :mod:`diffly.metrics.data` describes the left and right datasets *individually*, + so you can see how a change affects the data. + +The change default set is exposed as :data:`DEFAULT_METRICS`. + .. autodata:: MetricFn :no-value: -Presets -======= +.. autoclass:: Metric + +.. autodata:: DEFAULT_METRICS + :no-value: + +Change metrics +============== + +.. currentmodule:: diffly.metrics.change + +Metrics that describe the change between numeric columns by aggregating over +``right - left``. .. autosummary:: :toctree: _gen/ @@ -27,3 +51,22 @@ Presets mean_absolute_deviation mean_relative_deviation quantile + +.. autodata:: DEFAULT_CHANGE_METRICS + :no-value: + +Data metrics +============ + +.. currentmodule:: diffly.metrics.data + +Metrics that describe the left and right datasets individually, so you can +understand how a change affects the data. + +.. autosummary:: + :toctree: _gen/ + + null_fraction_change + +.. autodata:: DEFAULT_DATA_METRICS + :no-value: diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index c65320c..a6720c7 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -99,3 +99,26 @@ def test_cli_unknown_metric(tmp_path: Path) -> None: ) assert result.exit_code != 0 assert "Unknown metric" in result.output + + +@pytest.mark.parametrize("metric_name", ["Mean", "Null%"]) +def test_cli_metric_from_both_defaults(tmp_path: Path, metric_name: str) -> None: + # Both change ("mean") and data ("Null%") presets are selectable via --metric. + left = pl.DataFrame({"id": [1, 2], "x": [1.0, None]}) + right = pl.DataFrame({"id": [1, 2], "x": [1.0, 3.0]}) + left.write_parquet(tmp_path / "left.parquet") + right.write_parquet(tmp_path / "right.parquet") + + result = runner.invoke( + app, + [ + str(tmp_path / "left.parquet"), + str(tmp_path / "right.parquet"), + "--primary-key", + "id", + "--metric", + metric_name, + ], + ) + assert result.exit_code == 0 + assert metric_name in result.output diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..f3d3d5f --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_False_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_False_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..f3d3d5f --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_False_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..2f849f9 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_True_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_True_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..2f849f9 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_False_slim_True_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..18568f4 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,36 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_False_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_False_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..f2a498b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_False_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,39 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..06d07fe --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,24 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_True_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_True_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..01c654b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_False_top_True_slim_True_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,27 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..f3d3d5f --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_False_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_False_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..f3d3d5f --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_False_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..2f849f9 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_True_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_True_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..2f849f9 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_False_slim_True_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..18568f4 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,36 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_False_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_False_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..f2a498b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_False_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,39 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Diffly Summary ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..06d07fe --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,24 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_True_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_True_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..01c654b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_False_perfect_True_top_True_slim_True_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,27 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃ Null% ┃ str_len_delta ┃ Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..3a2a43b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_False_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_False_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..3a2a43b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_False_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..1316f6b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_True_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_True_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..1316f6b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_False_slim_True_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..bdca125 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,36 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_False_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_False_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..cdd7114 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_False_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,39 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..370a2d3 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,24 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_True_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_True_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..4a10c0c --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_False_top_True_slim_True_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,27 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..3a2a43b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_False_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_False_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..3a2a43b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_False_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,28 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..1316f6b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_True_sample_rows_True_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_True_sample_rows_True_sample_pk_False.txt new file mode 100644 index 0000000..1316f6b --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_False_slim_True_sample_rows_True_sample_pk_False.txt @@ -0,0 +1,16 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% (-20.0) │ │ + │ status │ 40.00% │ │ 0.0% -> 40.0% (+40.0) │ 0 │ + └────────┴────────────┴──────┴───────────────────────┴───────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_False_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_False_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..bdca125 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_False_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,36 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_False_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_False_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..cdd7114 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_False_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,39 @@ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃  Diffly Summary  ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + Primary key: id + + Schemas + ▔▔▔▔▔▔▔ + Schemas match exactly (column count: 3). + + Rows + ▔▔▔▔ + Left count Right count + 5 (no change) 5 + + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_True_sample_rows_False_sample_pk_False.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_True_sample_rows_False_sample_pk_False.txt new file mode 100644 index 0000000..370a2d3 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_True_sample_rows_False_sample_pk_False.txt @@ -0,0 +1,24 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x) │ + │ │ │ │ (+40.0) │ │ "c" -> "x" (1x) │ + │ │ │ │ │ │ "b" -> None (1x) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_True_sample_rows_True_sample_pk_True.txt b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_True_sample_rows_True_sample_pk_True.txt new file mode 100644 index 0000000..4a10c0c --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/gen/pretty_True_perfect_True_top_True_slim_True_sample_rows_True_sample_pk_True.txt @@ -0,0 +1,27 @@ + Rows + ▔▔▔▔ + ┏━┯━┯━┯━┯━┓╌╌╌┏━┯━┯━┯━┯━┓╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ + ┃ │ │ │ │ ┃ = ┃ │ │ │ │ ┃ 2 equal (40.00%) │ + ┠─┼─┼─┼─┼─┨╌╌╌┠─┼─┼─┼─┼─┨╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌├╴ 5 joined + ┃ │ │ │ │ ┃ ≠ ┃ │ │ │ │ ┃ 3 unequal (60.00%) │ + ┗━┷━┷━┷━┷━┛╌╌╌┗━┷━┷━┷━┷━┛╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ + + Columns + ▔▔▔▔▔▔▔ + ┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ + ┃ Column ┃ Match Rate ┃ Mean ┃  Null% ┃ str_len_delta ┃  Top Changes ┃ + ┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩ + │ price  │ 40.00% │ 0.75 │ 20.0% -> 0.0% │ │ None -> 30.0 │ + │ │ │ │ (-20.0) │ │ (1x, e.g. 3) │ + │ │ │ │ │ │ 40.0 -> 42.0 │ + │ │ │ │ │ │ (1x, e.g. 4) │ + │ │ │ │ │ │ 20.0 -> 21.0 │ + │ │ │ │ │ │ (1x, e.g. 2) │ + ├────────┼────────────┼──────┼───────────────────┼───────────────┼──────────────────┤ + │ status │ 40.00% │ │ 0.0% -> 40.0% │ 0 │ "d" -> None (1x, │ + │ │ │ │ (+40.0) │ │ e.g. 4) │ + │ │ │ │ │ │ "c" -> "x" (1x, │ + │ │ │ │ │ │ e.g. 3) │ + │ │ │ │ │ │ "b" -> None (1x, │ + │ │ │ │ │ │ e.g. 2) │ + └────────┴────────────┴──────┴───────────────────┴───────────────┴──────────────────┘ diff --git a/tests/summary/fixtures/metrics_null_fraction/test_metrics_null_fraction.py b/tests/summary/fixtures/metrics_null_fraction/test_metrics_null_fraction.py new file mode 100644 index 0000000..9e26bd4 --- /dev/null +++ b/tests/summary/fixtures/metrics_null_fraction/test_metrics_null_fraction.py @@ -0,0 +1,45 @@ +# Copyright (c) QuantCo 2025-2026 +# SPDX-License-Identifier: BSD-3-Clause + +import polars as pl +import polars.selectors as cs +import pytest + +from diffly import compare_frames, metrics +from diffly.metrics import Metric +from diffly.metrics.data import DEFAULT_DATA_METRICS +from tests.utils import generate_summaries + + +@pytest.mark.generate +def test_generate() -> None: + left = pl.DataFrame( + { + "id": [1, 2, 3, 4, 5], + "price": [10.0, 20.0, None, 40.0, 50.0], + "status": ["a", "b", "c", "d", "e"], + } + ) + right = pl.DataFrame( + { + "id": [1, 2, 3, 4, 5], + "price": [10.0, 21.0, 30.0, 42.0, 50.0], + "status": ["a", None, "x", None, "e"], + } + ) + comp = compare_frames(left, right, primary_key=["id"]) + generate_summaries( + comp, + metrics={ + # Numeric-only preset alongside a metric applied to all columns. + "Mean": metrics.mean, + "Null%": DEFAULT_DATA_METRICS["Null%"], + # A user-supplied metric with a custom (string-only) selector. + "str_len_delta": Metric( + fn=lambda left, right: ( + right.str.len_chars() - left.str.len_chars() + ).mean(), + selector=cs.string(), + ), + }, + ) diff --git a/tests/test_metrics.py b/tests/test_metrics.py index add8bd0..27f5825 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -2,12 +2,13 @@ # SPDX-License-Identifier: BSD-3-Clause import math +from typing import Any import polars as pl import pytest from diffly import metrics -from diffly.metrics import MetricFn +from diffly.metrics import MetricFn, data @pytest.fixture @@ -16,7 +17,7 @@ def frame() -> pl.DataFrame: return pl.DataFrame({"l": [1, 2, 3, None], "r": [1, 2, 5, 4]}) -def _apply(metric: MetricFn, frame: pl.DataFrame) -> float: +def _apply(metric: MetricFn, frame: pl.DataFrame) -> Any: return frame.select(metric(pl.col("l"), pl.col("r"))).item() @@ -64,6 +65,24 @@ def test_mean_relative_deviation_div_by_zero() -> None: assert math.isinf(_apply(metrics.mean_relative_deviation, frame)) +def test_null_fraction_change() -> None: + # left nulls: 1/4 = 25%; right nulls: 3/4 = 75%; delta = +50% + frame = pl.DataFrame({"l": [1, None, 3, 4], "r": [None, None, 3, None]}) + assert _apply(data.null_fraction_change, frame) == "25.0% -> 75.0% (+50.0)" + + +def test_null_fraction_change_negative_delta() -> None: + # left nulls: 1/2 = 50%; right nulls: 0%; delta = -50% + frame = pl.DataFrame({"l": [1, None], "r": [1, 2]}) + assert _apply(data.null_fraction_change, frame) == "50.0% -> 0.0% (-50.0)" + + +def test_null_fraction_change_non_numeric() -> None: + # Applies to any column type; here strings. left nulls: 0%; right nulls: 50% + frame = pl.DataFrame({"l": ["a", "b"], "r": ["a", None]}) + assert _apply(data.null_fraction_change, frame) == "0.0% -> 50.0% (+50.0)" + + def test_quantile(frame: pl.DataFrame) -> None: # deltas [0, 0, 2]: p50 = 0, p100 = 2 assert _apply(metrics.quantile(0.5), frame) == 0 @@ -73,3 +92,12 @@ def test_quantile(frame: pl.DataFrame) -> None: def test_quantile_out_of_range() -> None: with pytest.raises(ValueError, match="q must be in"): metrics.quantile(1.5) + + +def test_default_metrics_partition() -> None: + from diffly.metrics import change + + # The top-level defaults consist of the change metrics only. + assert metrics.DEFAULT_METRICS == {**change.DEFAULT_CHANGE_METRICS} + assert set(change.DEFAULT_CHANGE_METRICS) & set(data.DEFAULT_DATA_METRICS) == set() + assert list(metrics.DEFAULT_METRICS) == [*change.DEFAULT_CHANGE_METRICS]