A Pre-Modeling Statistical Audit Framework for Evaluating Dataset Readiness Before Predictive Modeling
PrismR is an open-source R statistical engineering package that introduces the formal concept of Model Readiness—a rigorous statistical audit verifying whether tabular data is genuinely suitable for machine learning before any model is trained.
In modern data science, teams routinely spend weeks fine-tuning hyperparameter grids, selecting gradient boosting architectures, and engineering deep networks, only to suffer from models that:
PrismR eliminates this entire class of failures by establishing a Statistical Validation Layer between preprocessing and model training.
Traditional ML Pipeline (Vulnerable):
Raw Data ──► Data Cleaning ──► Feature Engineering ──► Model Training
▲
└── [Silent failures discovered in production]
PrismR Pipeline (Hardened):
Raw Data ──► Data Cleaning ──► ┌────────────────────────────────────┐
│ Statistical Validation Layer │ ◄── PrismR Gatekeeper
│ (Quality • Leakage • Transforms │
│ • Feature Stability) │
└─────────────────┬──────────────────┘
│ [Verdict: Model Ready]
▼
Feature Engineering ──► Model Training
A physical glass prism does not generate new light; it takes white light and refracts it into its constituent wavelengths, exposing invisible components hidden within the beam.
Similarly, PrismR does not mutate or alter your dataset. Instead, it passes tabular data through a four-stage statistical refraction chamber to reveal latent data quality flaws, leakage pathways, mathematical transformation requirements, and covariate drift:
Tabular Dataset
│
▼
[ PrismR ]
│
┌─────────────────────────┼─────────────────────────┐
▼ ▼ ▼
Data Quality Leakage Safety Feature Stability
- Missingness - Key/ID Columns - Population Stability Index
- Duplicate Rows - Duplicate Features - Scale-Normalized Wasserstein
- Constant Columns - Cardinality Extremes - Bayesian Laplace Smoothing
- Target Correlation
│
▼
Transformation Analysis
- Unbiased Sample Skewness
- Excess Kurtosis (Tails)
- Strict Positivity Constraints
- Box-Cox / Yeo-Johnson / Log
│
▼
Dual-Layer Model Readiness Score
(Weighted Score + Hard Vetoes)
install.packages("PrismR")
# Install using remotes (recommended)
install.packages("remotes")
# remotes::install_github("Arshit-dv/PrismR")
install.packages("PrismR", repos = c('https://arshit-dv.r-universe.dev', 'https://cloud.r-project.org'))
# Or using pak (fastest)
install.packages("pak")
pak::pkg_install("Arshit-dv/PrismR")
PrismR evaluates dataset health in three simple lines of R:
# Install from GitHub
# # devtools::install_github("Arshit-dv/PrismR")
install.packages("PrismR", repos = c('https://arshit-dv.r-universe.dev', 'https://cloud.r-project.org'))
library(PrismR)
# Run full validation on any tabular data frame
report <- prism(airquality, target = "Ozone")
summary(report)
summary(report)
=========================================================
Prism Summary
=========================================================
Model Readiness : 96.5
Overall Verdict : Proceed with Caution
Data Quality
-----------------------------------------
Data Quality Score : 97.6/100 (Excellent)
Leakage Detection
-----------------------------------------
Leakage Safety Score : 100/100 (Safe)
Transformation Analysis
-----------------------------------------
1 variable(s) require transformation.
• Ozone → Box-Cox
Feature Stability
-----------------------------------------
Overall Stability Score : 43.3/100
Stability Verdict : Drift Warning (Unstable Features Detected)
Stable Features : 0
Moderate Drift : 2
Unstable Features : 4
⚠ Unstable Features:
• Solar.R
• Wind
• Temp
• Month
Moderate Drift:
• Ozone
• Day
print(report)
print(report)
=========================================================
Prism Report
=========================================================
Model Readiness : 96.5
Overall Verdict : Proceed with Caution
=========================================================
Data Quality
=========================================================
Quality Score : 97.6 /100
Verdict : Excellent
Missing Values : 4.79 %
Duplicate Rows : 0
Constant Columns : 0
✓ No major data quality issues detected.
=========================================================
Leakage Detection
=========================================================
Leakage Safety Score : 100 /100
Verdict : Safe
Identifier Columns : 0
Duplicate Columns : 0
High Cardinality : 0
Target Leakage : 0
Correlation Leakage : 0
✓ No potential leakage detected.
=========================================================
Transformation Analysis
=========================================================
Numeric Variables Analysed : 6
Transformations Needed : 1
Variable Finding Recommendation
----------------------------------------------------------------------
Ozone Severely right-skewed Box-Cox
✓ Remaining 5 variables require no transformation.
=========================================================
Feature Stability
=========================================================
Overall Stability Score : 43.3 /100
Verdict : Drift Warning (Unstable Features Detected)
Evaluated Features : 6
Stable Features : 0
Moderate Drift : 2
Unstable Features : 4
Unstable Features (Drift Detected)
----------------------------------
• Solar.R (PSI: 0.3718)
• Wind (PSI: 0.2610)
• Temp (PSI: 0.5042)
• Month (PSI: 5.0878)
Moderate Drift
--------------
• Ozone (PSI: 0.1691)
• Day (PSI: 0.1118)
plot(report)
PrismR features an automated, publication-ready data visualization engine built on ggplot2 and ggrepel. It translates complex statistical diagnostics into four distinct visual paradigms.
# 1. Macro Dataset Health Gauge (Concentric Radial Arcs)
plot(report, type = "radial")
# 2. Feature Diagnostic Rose (Nightingale Coxcomb)
plot(report, type = "circular")
# 3. Statistical Feature Map (Completeness vs. Skewness Plane)
plot(report, type = "bubble")
# 4. Single-Feature Radar Profile (Multi-Spoke Spider Chart)
plot(report, type = "radar", feature = "Solar.R")
type = "radial")The Health Gauge renders concentric polar progress arcs visualizing macro-level readiness alongside each diagnostic sub-score. Reference tick marks at 25%, 50%, 75%, and 100% provide immediate calibration.

type = "circular")Inspired by Florence Nightingale’s polar area diagrams, the Diagnostic Rose provides a feature-by-feature forensic breakdown mapped around an open donut ring.

Ozone with 24.2% missingness) display visibly indented petals.None, Log, Box-Cox, Yeo-Johnson, or Categorical).type = "bubble")The Feature Map projects every feature onto an analytical 2D coordinate system: Feature Completeness (%) on the horizontal axis versus Distribution Skewness on the vertical axis.

ggrepel leader lines and deterministic jittering to prevent overlapping labels even in dense multi-variable datasets.type = "radar", feature = "col")The Radar Profile isolates an individual feature and inspects its performance across 5+1 core statistical axes on a spider web chart.

PrismR is designed as a decoupled, modular framework. Each underlying engine can be invoked as an independent, standalone function:
┌──────────────────────────────┐
│ PrismR Core │
└──────────────┬───────────────┘
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
quality_score() detect_leakage() recommend_transform()
│ │ │
└───────────────────────┼───────────────────────┘
▼
feature_stability()
quality_score)Data quality failures are rarely uniform. A dataset might contain zero missing values overall, but have one feature with 95% missingness, duplicate rows that cause data leakage between train and test splits, or zero-variance columns that cause matrix singularity.
NA / NaN cells across the matrix.$$\text{Quality Score} = \max\left(0,, 100 - \left(0.50 \times \text{Missing Pct} + 0.30 \times \text{Duplicate Row Pct} + 0.20 \times \text{Constant Col Pct}\right)\right)$$
q <- quality_score(airquality)
# Access top-level metrics
q$quality_score # 97.6 / 100
q$missing_percent # 4.79 %
q$duplicate_rows # 0
q$constant_columns # character(0)
q$n_constant_columns # 0
# Feature-level quality breakdown
head(q$variables)
detect_leakage)Data leakage is the silent killer of predictive models. It occurs when features contain information about the target variable that will not be available at inference time, or when surrogate database keys are inadvertently included as predictors.
id, uuid, cust_id, hash, or row index features).$$\text{Leakage Score} = \max\left(0, 100 - \left(\frac{N_{\text{id}}}{N_{\text{cols}}} \times 25 + \frac{N_{\text{dup}}}{N_{\text{cols}}} \times 20 + \frac{N_{\text{card}}}{N_{\text{cols}}} \times 20 + 20 \times \mathbb{I}{\text{target}} + 15 \times \mathbb{I}{\text{corr}}\right)\right)$$
# Synthetic dataset with an injected ID and target leaker
sample_df <- data.frame(
customer_id = paste0("ID_", 1:100),
age = rnorm(100, mean = 40, sd = 10),
target = rnorm(100, mean = 500, sd = 50)
)
sample_df$leaker_feature <- sample_df$target * 1.0000001 # Leaker column
leakage <- detect_leakage(sample_df, target = "target")
leakage$leakage_score # Overall Safety Score (0 - 100)
leakage$identifier_columns # "customer_id"
leakage$target_leakage # "leaker_feature"
leakage$correlation_leakage # "leaker_feature"
leakage$variables # Feature-level leakage diagnostic table
recommend_transform)Linear regression, logistic models, linear discriminant analysis, neural networks, PCA, and distance-based clustering assume roughly symmetric distributions without extreme leverage points.
e1071).| Distributional Property | Domain Condition | Recommended Transform | Mathematical Rationale |
|---|---|---|---|
| $ | \gamma_1 | \le 0.5$ | Any |
| $0.5 < \gamma_1 \le 1.0$ | $\min(x) > 0$ | Log | Moderate right-skew; $\ln(x)$ compresses large values. |
| $\gamma_1 > 1.0$ | $\min(x) > 0$ | Box-Cox | Severe right-skew; parametric power transform $y^{(\lambda)}$ optimizes normality. |
| $ | \gamma_1 | > 0.5$ | $\min(x) \le 0$ |
| Discrete / Factor | String / Factor | Categorical | High-skew discrete levels requiring one-hot or target encoding. |
t <- recommend_transform(airquality)
# Actionable recommendations (features requiring transformation)
t$recommendations
# variable skewness kurtosis finding recommendation
# 1 Ozone 1.241796 1.290303 Severely right-skewed Box-Cox
# Full variable table across all numeric columns
t$variables[, c("variable", "skewness", "kurtosis", "finding", "recommendation")]
feature_stability)Covariate shift (distribution drift) occurs when the input distribution $P(X)$ changes between training and inference, invalidating the model even if the underlying relationship $P(Y|X)$ remains constant.
verbose = FALSE), returning structured programmatic lists ideal for automated CI/CD pipelines.| PSI Metric | Drift Classification | Variable Score | Engineering Action Required |
|---|---|---|---|
| $\text{PSI} < 0.10$ | 🟩 Stable | 100 | Insignificant shift. Feature is safe for modeling. |
| $0.10 \le \text{PSI} < 0.25$ | 🟨 Moderate Drift | 70 | Slight shift. Apply L1/L2 regularization or monitor in production. |
| $\text{PSI} \ge 0.25$ | 🟥 Unstable | 30 | Critical drift. Hard veto: Drop feature or retrain pipeline. |
Evaluates temporal drift between the first 50% (baseline) and last 50% (current) of rows:
s <- feature_stability(airquality)
s$stability_score # Continuous score (0 - 100)
s$verdict # "Drift Warning (Unstable Features Detected)"
s$unstable_features # c("Solar.R", "Wind", "Temp", "Month")
head(s$variables) # Feature-level PSI, Wasserstein, and status
Compares a reference training set against a live production batch:
s <- feature_stability(train_data, current = prod_data)
Set verbose = TRUE for an ASCII terminal report:
s <- feature_stability(airquality, verbose = TRUE)
PrismR combines all four modules into a unified decision engine.
$$\text{Readiness Score} = 0.40 \times \text{Quality} + 0.45 \times \text{Leakage} + 0.15 \times \text{Transform Health}$$
[!IMPORTANT] The Averaging Fallacy: In naive composite scoring systems, a dataset with 100% data quality and perfect transformations could achieve an average score of 95/100 despite having a critical target leaker or severe distribution drift.
PrismR prevents this by enforcing hard architectural vetoes:
| Overall Verdict | Conditions Required | Meaning & Pipeline Action |
|---|---|---|
| 🟢 Model Ready | Score $\ge 85$ AND Leakage $\ge 80$ AND 0 Unstable Features | Dataset is statistically sound. Proceed directly to model training. |
| 🟡 Proceed with Caution | Score $\ge 65$ AND Leakage $\ge 50$ (or moderate drift) | Minor defects detected (moderate skew, light missingness). Review flagged items. |
| 🔴 Action Required | Score $< 65$ OR Leakage $< 50$ OR $\ge 1$ Unstable Feature | Hard Veto Triggered. Training on this data will produce invalid models. Remediate blockers. |
When PrismR flags issues across multiple modules, in what order should a data scientist resolve them?
Trying to optimize transformations on a feature that leaks the target, or imputing values on a column that suffers from severe temporal drift, is wasted engineering effort. PrismR establishes a structured 4-Phase Remediation Protocol:
[ RAW TABULAR DATA ]
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Phase 1: Data Leakage (`detect_leakage`) │ ◄── PRIORITY 1: DROP / ISOLATE
│ Action: Remove ID keys, exact target leakers, proxy vectors │ (Hard Veto Blocker)
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Phase 2: Data Quality (`quality_score`) │ ◄── PRIORITY 2: CLEANSE
│ Action: Deduplicate rows, drop zero-variance constants, │ (Structural Hygiene)
│ impute or drop heavy-missingness columns │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Phase 3: Feature Stability (`feature_stability`) │ ◄── PRIORITY 3: STABILIZE
│ Action: Audit covariate shift across time/batches. │ (Distribution Shift)
│ Resolve drift BEFORE attempting mathematical transforms!
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Phase 4: Transformations (`recommend_transform`) │ ◄── PRIORITY 4: OPTIMIZE
│ Action: Apply Box-Cox / Log / Yeo-Johnson to clean, stable │ (Model Convergence)
│ features for symmetry and linear convergence │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Final Gate: `prism()` Report Certification │ ◄── GREEN LIGHT: "Model Ready"
│ Action: Verify Readiness >= 85 and 0 Veto Blockers │
└─────────────────────────────────────────────────────────────┘
[!WARNING] Mathematical Reality: Transformations Do NOT Cure Distribution Drift. If a variable exhibits severe temporal drift ($\text{PSI} \ge 0.25$), applying a mathematical transform like Box-Cox or Log only reshapes the distribution within each partition—the underlying covariate shift between reference and production remains intact!
Log, Box-Cox, or Yeo-Johnson) to achieve normality and enhance model convergence.PrismR supports two complementary operational modes:
Invoke individual standalone functions interactively during exploratory data analysis (EDA) to isolate specific components:
# Check leakage first before touching anything else
leaks <- detect_leakage(df, target = "outcome")
df <- df[, !names(df) %in% leaks$identifier_columns]
# Check quality and missingness
q <- quality_score(df)
# Check stability between train and test
s <- feature_stability(train_df, current = test_df)
# Check transformation needs on verified features
t <- recommend_transform(df)
prism() in CI/CD & Production)Use prism() as an automated gatekeeper before fitting machine learning models or deploying pipelines to production:
report <- prism(data, target = "outcome", current = eval_data)
# Hard programmatic gate
if (report$verdict != "Model Ready") {
stop("Dataset failed Model Readiness validation! Inspect report before training.")
}
Here is how a practitioner uses PrismR from raw data ingestion to production validation:
library(PrismR)
# 1. Load raw training data
data("airquality")
# 2. Run PrismR validation gate
report <- prism(airquality, target = "Ozone")
# 3. Inspect high-level verdict
summary(report)
# 4. If verdict is "Proceed with Caution" or "Action Required", inspect the print audit
if (report$verdict != "Model Ready") {
print(report)
}
# 5. Visualize feature health
plot(report, type = "radial") # Check macro gauge
plot(report, type = "circular") # Identify which features need attention
plot(report, type = "bubble") # Review skewness and missingness plane
# 6. Apply targeted remediations:
# - Impute missing values for Ozone
# - Apply Box-Cox transform to Ozone
# - Address seasonal temperature/solar drift before fitting
PrismR is engineered strictly according to CRAN and R-core packaging guidelines:
PrismReport S3 class supporting idiomatic print(), summary(), and plot() generic methods.stats, utils, e1071, ggplot2, and ggrepel.testthat suite verifying input assertions, boundary conditions, edge cases, and graphic rendering.# Run comprehensive package test suite
devtools::test()
PrismR combines rigorous statistical methodology with production-grade engineering:
ggplot2 diagnostic visualizations (radial macro gauge, circular diagnostic rose, bubble skewness map, radar dimensional profile).testthat.R CMD check --as-cran.pkgdown and Bootstrap 5 hosted via GitHub Pages.