Skip to main content

datarust_profile/
lib.rs

1//! # datarust-profile
2//!
3//! One-call data profiling and data-quality reports for the
4//! [datarust](https://crates.io/crates/datarust) ecosystem.
5//!
6//! `datarust-profile` takes a numeric [`datarust::Matrix`], a categorical
7//! [`datarust::StrMatrix`], or a mixed table of both, and produces a
8//! [`DatasetProfile`] describing shape, memory footprint, duplicate rows,
9//! per-column descriptive statistics (mean, std, five-number summary,
10//! cardinality, top value) and a list of data-quality findings. Profiles can
11//! be rendered to JSON (via the `serde` feature) or to a self-contained HTML
12//! report with no extra dependencies.
13//!
14//! ## Quick start
15//!
16//! ```no_run
17//! use datarust::Matrix;
18//! use datarust_profile::{profile_matrix, report};
19//!
20//! let m = Matrix::from_rows(vec![
21//!     vec![1.0, 10.0],
22//!     vec![2.0, 12.0],
23//!     vec![3.0, f64::NAN],
24//! ]).unwrap();
25//!
26//! let profile = profile_matrix(&m, None).unwrap();
27//! println!("{}x{}, {} duplicates",
28//!     profile.n_rows, profile.n_columns, profile.duplicate_rows);
29//!
30//! // HTML report (always available, no extra deps):
31//! let html = report::to_html(&profile);
32//! std::fs::write("profile.html", html).unwrap();
33//! ```
34//!
35//! ## JSON output (feature `serde`)
36//!
37//! Requires the `serde` feature. The example below is marked `ignore` so that
38//! it is not compiled by `cargo test --doc` when `serde` is disabled.
39//!
40//! ```rust,ignore
41//! use datarust::Matrix;
42//! use datarust_profile::{profile_matrix, report};
43//!
44//! let m = Matrix::from_rows(vec![vec![1.0]]).unwrap();
45//! let profile = profile_matrix(&m, None).unwrap();
46//! let json = report::to_json(
47//!     &report::JsonReport::from_profile(&profile),
48//! ).unwrap();
49//! std::fs::write("profile.json", json).unwrap();
50//! ```
51
52#![warn(missing_docs)]
53#![warn(clippy::all)]
54
55pub mod error;
56pub mod infer;
57pub mod profile;
58pub mod quality;
59pub mod report;
60pub mod types;
61
62pub use error::{ProfileError, Result};
63pub use profile::{
64    CategoricalStats, ColumnProfile, CorrelationMatrix, DatasetProfile, FiveNumber, Histogram,
65    NumericStats, PointBiserialEntry, Relationships,
66};
67pub use quality::{run_checks, QualityIssue, QualityKind, Thresholds};
68pub use types::{ColumnType, Severity};
69
70use datarust::{Matrix, StrMatrix};
71
72/// Profiles a numeric [`Matrix`].
73///
74/// `names` optionally supplies column names; when `None` (or the wrong length)
75/// columns are named `x0..x{n-1}`.
76pub fn profile_matrix(m: &Matrix, names: Option<&[String]>) -> Result<DatasetProfile> {
77    DatasetProfile::from_matrix(m, names)
78}
79
80/// Profiles a numeric [`Matrix`] and sets a designated target column for leakage detection.
81pub fn profile_matrix_with_target(
82    m: &Matrix,
83    names: Option<&[String]>,
84    target: &str,
85) -> Result<DatasetProfile> {
86    let profile = DatasetProfile::from_matrix(m, names)?;
87    Ok(profile.with_target(target))
88}
89
90/// Profiles a string [`StrMatrix`], inferring each column's type.
91pub fn profile_str_matrix(m: &StrMatrix, names: Option<&[String]>) -> Result<DatasetProfile> {
92    DatasetProfile::from_str_matrix(m, names)
93}
94
95/// Profiles a mixed table: a numeric [`Matrix`] block followed by a
96/// categorical [`StrMatrix`] block, both with the same row count.
97///
98/// `names` must have one entry per column across both blocks (numerics first).
99pub fn profile_table(
100    numeric: Option<&Matrix>,
101    categorical: Option<&StrMatrix>,
102    names: &[String],
103) -> Result<DatasetProfile> {
104    DatasetProfile::from_table(numeric, categorical, names)
105}
106
107/// Profiles a mixed table and sets a designated target column for leakage detection.
108pub fn profile_table_with_target(
109    numeric: Option<&Matrix>,
110    categorical: Option<&StrMatrix>,
111    names: &[String],
112    target: &str,
113) -> Result<DatasetProfile> {
114    let profile = DatasetProfile::from_table(numeric, categorical, names)?;
115    Ok(profile.with_target(target))
116}