PROC COMPARE - Part 02: CRITERION= Tolerance, ID= Variable Matching, and QC Workflows
Overview
Part 01 covered the fundamentals of PROC COMPARE: comparing dataset structure, variable attributes, and observation values.
This lesson builds on that foundation with three practical extensions: numeric tolerance via CRITERION=, key-based observation matching via ID=, and using PROC COMPARE systematically in a QC or validation workflow.
These techniques are especially useful in clinical programming where datasets are compared across production and validation environments.
Numeric Tolerance with CRITERION=
By default, PROC COMPARE flags any numeric difference, no matter how small — even a floating-point rounding difference at the 15th decimal place will be reported as a discrepancy.
The CRITERION= option sets a relative tolerance threshold. Two values are considered equal if their absolute difference divided by the larger absolute value is less than the criterion.
The default criterion is 1E-15. For most clinical QC purposes, a criterion of 1E-8 or 1E-6 is sufficient to ignore floating-point noise while still catching meaningful differences.
Use CRITERION= when comparing derived statistics such as means, percentages, or change-from-baseline values that may differ slightly due to floating-point arithmetic.
SAS Log
Run both PROC COMPARE calls and examine the log output carefully.
The first call with default CRITERION= will likely report differences in all three rows because the values differ at the 13th-14th decimal place.
The second call with CRITERION=1E-8 should report a clean compare with no value differences, because all differences are far smaller than the threshold.
Choose your criterion thoughtfully — setting it too high risks masking real data differences; setting it at the default risks noise from floating-point arithmetic overwhelming your QC results.
Matching Observations by Key Variable with ID=
By default, PROC COMPARE matches observations by their position: the first row of BASE is compared with the first row of COMPARE, the second with the second, and so on.
Position-based matching breaks down when the two datasets have different sort orders or different numbers of rows — mismatched positions produce misleading discrepancy reports.
The ID= option instructs PROC COMPARE to match observations by the value of one or more key variables, similar to a BY-key merge.
Both datasets must be sorted by the ID variable(s) before running PROC COMPARE with ID=.
Observations present in one dataset but not the other are reported as exclusive observations rather than value differences.
SAS Log
WORK.QC is deliberately in a different order and contains an extra row (003/visit 2) and a changed value (001/visit 2: result is 13 in QC vs 12 in PROD).
With ID=subject visit, PROC COMPARE matches on the key combination rather than row position, so the sort order difference in QC does not cause false discrepancies.
The log will report the value difference for subject 001 visit 2, and will flag subject 003 visit 2 as exclusive to the COMPARE dataset.
Review the "Observation Summary" section in the output to confirm how many observations were matched, and the "Values Comparison Summary" for the count of variables with differences.
Capturing PROC COMPARE Results Programmatically with OUTNOEQUAL and OUT=
When running PROC COMPARE in a QC workflow, you often want to capture the differences in a dataset for reporting or further analysis rather than relying on reading the log.
The OUT= option writes a comparison output dataset. Combined with OUTNOEQUAL, only rows with at least one difference are written — rows that match perfectly are excluded.
The LISTALL option in the PROC COMPARE statement makes the output more complete by including all observations, not just those with differences.
SAS Log
WORK.DIFFS will contain one row per variable per observation where a difference was detected, along with the BASE and COMPARE values and the difference amount.
The DATA _NULL_ step checks whether WORK.DIFFS has any rows and writes a summary message to the log — this is a clean pattern for automated QC pipelines where you want a clear pass/fail indicator.
Inspect WORK.DIFFS to confirm it contains only the discrepant rows identified in the previous step.
Dataset View
Macro-Driven QC Pattern
In production QC environments, it is common to compare many datasets in a single pass using a macro loop.
The following macro accepts a dataset name, runs PROC COMPARE, and writes a one-line summary to a running QC log dataset.
This pattern allows a QC programmer to run comparisons on dozens of datasets and collect all results in a single report dataset.
SAS Log
This macro is a template to illustrate the pattern — in practice you would call it once per dataset pair in your QC plan.
The NOPRINT option suppresses PROC COMPARE output to the SAS output window, keeping the log clean when running many comparisons.
%SYSFUNC(exist()) guards against the macro crashing when a dataset is missing — this is good defensive programming for QC workflows.
WORK.QC_SUMMARY accumulates one row per dataset compared, allowing a final report of all comparison results.
Key Points
CRITERION= controls numeric tolerance in PROC COMPARE — the default is 1E-15 which may flag floating-point noise; relax to 1E-8 or 1E-6 for practical QC comparisons.
ID= matches observations by key variable values rather than row position — always sort both datasets by the ID variables before running PROC COMPARE with ID=.
OUT= with OUTNOEQUAL captures only differing rows in a dataset, enabling programmatic pass/fail checks without reading the log.
NOPRINT suppresses log and output window detail — useful in macro-driven QC loops where you capture results in a summary dataset instead.
Always check for exclusive observations (rows present in one dataset only) as well as value differences — both types of discrepancy matter for QC.