Report API¶
DataComPy’s datacompy.report module provides a typed data model where
every backend produces a ReportData instance via
compare.build_report_data(). Rendering methods (render(),
to_html(), save(), to_dict()) live directly on ReportData,
making it easy to build custom dashboards, export to JSON, or plug in
alternative templates.
Programmatic Access¶
Call compare.build_report_data() on any compare object to get a
ReportData instance without triggering
any rendering:
import pandas as pd
from datacompy import PandasCompare
df1 = pd.DataFrame({"id": [1, 2, 3], "val": [10, 20, 30]})
df2 = pd.DataFrame({"id": [1, 2, 3], "val": [10, 99, 30]})
compare = PandasCompare(df1, df2, join_columns="id")
data = compare.build_report_data()
# Inspect structured fields directly
print(data.row_summary.unequal_rows) # 1
print(data.mismatch_stats.stats[0].column) # 'val'
print(data.column_summary.common_columns) # 2
The same method is available on all backends (PolarsCompare,
SparkSQLCompare, SnowflakeCompare).
Rendering and Export¶
Rendering methods live on ReportData directly:
data = compare.build_report_data()
# Plain-text report (same output as compare.report())
print(data.render())
# Save as HTML file
data.save("comparison.html")
# JSON-serializable dict (for dashboards / APIs)
import json
payload = json.dumps(data.to_dict())
Custom Templates¶
Pass a template_path to render() or save() to use your own Jinja2
template:
print(data.render(template_path="my_report.j2"))
data.save("report.html", template_path="my_report.j2")
The template receives the same context as the default
report_template.j2; see Template Customization Guide for the full variable
reference.
Data Classes¶
Typed data model for DataComPy report generation.
All backends produce a ReportData instance via
compare.build_report_data(). ReportData owns rendering to
text and HTML, and exposes to_dict() for programmatic consumers.
Examples
Programmatic access without rendering:
>>> data = compare.build_report_data()
>>> print(data.row_summary.unequal_rows)
>>> print(data.mismatch_stats.stats[0].column)
Render to text and save HTML:
>>> data = compare.build_report_data()
>>> print(data.render())
>>> data.save("comparison.html")
Export as JSON-serializable dict:
>>> import json
>>> json.dumps(data.to_dict())
- class datacompy.report.ColumnComparison(unequal_columns: int, equal_columns: int, unequal_values: int)
Bases:
objectAggregate column comparison counts.
- Variables:
unequal_columns (int) – Number of compared columns with at least one unequal value.
equal_columns (int) – Number of compared columns where all values matched.
unequal_values (int) – Total number of individual cell values that did not match.
- equal_columns: int
- unequal_columns: int
- unequal_values: int
- class datacompy.report.ColumnSummary(common_columns: int, df1_unique: int, df1_unique_columns: Tuple[str, ...], df2_unique: int, df2_unique_columns: Tuple[str, ...], df1_name: str, df2_name: str)
Bases:
objectSummary of column overlap between the two DataFrames.
- Variables:
common_columns (int) – Number of columns present in both DataFrames.
df1_unique (int) – Number of columns only in df1.
df1_unique_columns (tuple of str) – Names of columns only in df1.
df2_unique (int) – Number of columns only in df2.
df2_unique_columns (tuple of str) – Names of columns only in df2.
df1_name (str) – Label for the first DataFrame.
df2_name (str) – Label for the second DataFrame.
- common_columns: int
- df1_name: str
- df1_unique: int
- df1_unique_columns: Tuple[str, ...]
- df2_name: str
- df2_unique: int
- df2_unique_columns: Tuple[str, ...]
- class datacompy.report.MismatchStat(column: str, dtype1: str, dtype2: str, unequal_cnt: int, max_diff: float, null_diff: int, rel_tol: float, abs_tol: float)
Bases:
objectPer-column mismatch statistics.
- Variables:
column (str) – Column name.
dtype1 (str) – Data type in df1.
dtype2 (str) – Data type in df2.
unequal_cnt (int) – Number of rows where the values differ.
max_diff (float) – Maximum absolute numeric difference (0.0 for non-numeric columns).
null_diff (int) – Number of rows where one value is null and the other is not.
rel_tol (float) – Relative tolerance applied to this column.
abs_tol (float) – Absolute tolerance applied to this column.
- abs_tol: float
- column: str
- dtype1: str
- dtype2: str
- max_diff: float
- null_diff: int
- rel_tol: float
- unequal_cnt: int
- class datacompy.report.MismatchStats(has_mismatches: bool, has_samples: bool, stats: Tuple[MismatchStat, ...] = (), samples: Tuple[str, ...] = (), df1_name: str = '', df2_name: str = '')
Bases:
objectMismatch statistics across all compared columns.
- Variables:
has_mismatches (bool) – True when at least one column has unequal values or types.
has_samples (bool) – True when sample rows are available for display.
stats (tuple of MismatchStat) – Per-column statistics, sorted by column name.
samples (tuple of str) – Pre-rendered string tables of sample mismatched rows (one per column).
df1_name (str) – Label for the first DataFrame.
df2_name (str) – Label for the second DataFrame.
- df1_name: str = ''
- df2_name: str = ''
- has_mismatches: bool
- has_samples: bool
- samples: Tuple[str, ...] = ()
- stats: Tuple[MismatchStat, ...] = ()
- class datacompy.report.ReportData(df1_name: str, df2_name: str, df1_shape: Tuple[int, int], df2_shape: Tuple[int, int], column_count: int, column_summary: ColumnSummary, row_summary: RowSummary, column_comparison: ColumnComparison, mismatch_stats: MismatchStats, df1_unique_rows: UniqueRowsData, df2_unique_rows: UniqueRowsData)
Bases:
objectComplete data model for a DataComPy comparison report.
Produced by
compare.build_report_data(). All fields are immutable so the object can be safely cached or passed across threads.- Variables:
df1_name (str) – Label for the first DataFrame.
df2_name (str) – Label for the second DataFrame.
df1_shape (tuple of (int, int)) –
(rows, columns)of df1.df2_shape (tuple of (int, int)) –
(rows, columns)of df2.column_count (int) – Maximum number of columns displayed in unique-row samples.
column_summary (ColumnSummary)
row_summary (RowSummary)
column_comparison (ColumnComparison)
mismatch_stats (MismatchStats)
df1_unique_rows (UniqueRowsData)
df2_unique_rows (UniqueRowsData)
- column_comparison: ColumnComparison
- column_count: int
- column_summary: ColumnSummary
- df1_name: str
- df1_shape: Tuple[int, int]
- df1_unique_rows: UniqueRowsData
- df2_name: str
- df2_shape: Tuple[int, int]
- df2_unique_rows: UniqueRowsData
- mismatch_stats: MismatchStats
- render(template_path: str | None = None) str
Render the report to a text string.
- Parameters:
template_path (str, optional) – Path to a custom Jinja2 template. When
Nonethe defaultreport_template.j2is used.- Returns:
Formatted report text.
- Return type:
str
- row_summary: RowSummary
- save(path: str | Path, template_path: str | None = None) None
Save the report as an HTML file.
- Parameters:
path (str or Path) – Destination file path. Parent directories are created if needed.
template_path (str, optional) – Path to a custom Jinja2 template. When
Nonethe defaultreport_template.j2is used.
- to_dict() Dict[str, Any]
Return the report data as a JSON-serializable dict.
- Returns:
dataclasses.asdict(self)— safe forjson.dumps().- Return type:
dict
- to_html(template_path: str | None = None) str
Return the report wrapped in a minimal HTML page.
- Parameters:
template_path (str, optional) – Path to a custom Jinja2 template. When
Nonethe defaultreport_template.j2is used.- Returns:
HTML string with the text report inside a
<pre>block.- Return type:
str
- class datacompy.report.RowSummary(match_columns: Tuple[str, ...], on_index: bool, has_duplicates: bool, abs_tol: Any, rel_tol: Any, common_rows: int, df1_unique: int, df2_unique: int, unequal_rows: int, equal_rows: int, df1_name: str, df2_name: str)
Bases:
objectSummary of row overlap and match statistics.
- Variables:
match_columns (tuple of str) – Column(s) used to join/match rows. Empty tuple when matching on index.
on_index (bool) – True when the comparison was joined on DataFrame index rather than columns.
has_duplicates (bool) – Whether duplicate join-key values were found.
abs_tol (float or dict) – Absolute tolerance used for numeric comparisons.
rel_tol (float or dict) – Relative tolerance used for numeric comparisons.
common_rows (int) – Number of rows present in both DataFrames after joining.
df1_unique (int) – Number of rows only in df1.
df2_unique (int) – Number of rows only in df2.
unequal_rows (int) – Number of common rows where at least one compared column differs.
equal_rows (int) – Number of common rows where all compared columns match.
df1_name (str) – Label for the first DataFrame.
df2_name (str) – Label for the second DataFrame.
- abs_tol: Any
- common_rows: int
- df1_name: str
- df1_unique: int
- df2_name: str
- df2_unique: int
- equal_rows: int
- has_duplicates: bool
- match_columns: Tuple[str, ...]
- on_index: bool
- rel_tol: Any
- unequal_rows: int
- class datacompy.report.UniqueRowsData(has_rows: bool, rows: str = '')
Bases:
objectSample rows that exist in only one of the two DataFrames.
- Variables:
has_rows (bool) – True when there is at least one unique row to display.
rows (str) – Pre-rendered string table of sample rows.
- has_rows: bool
- rows: str = ''