#![warn(missing_docs)]
#![warn(clippy::all)]
#[cfg(feature = "csv")]
pub mod csv;
pub mod error;
pub mod infer;
pub mod profile;
pub mod quality;
pub mod report;
pub mod types;
pub use error::{ProfileError, Result};
pub use profile::{
CategoricalStats, ColumnProfile, CorrelationMatrix, DatasetProfile, FiveNumber, Histogram,
NumericStats, PointBiserialEntry, Relationships,
};
pub use quality::{run_checks, QualityIssue, QualityKind, Thresholds};
pub use types::{ColumnType, Severity};
#[cfg(feature = "csv")]
pub use csv::{read_csv, read_csv_reader, read_csv_with, CsvReadOptions, CsvTable};
#[cfg(feature = "streaming")]
pub use streaming::{profile_csv_streaming, profile_csv_streaming_with, StreamingOptions};
#[cfg(feature = "streaming")]
pub mod streaming;
use datarust::{Matrix, StrMatrix};
pub fn profile_matrix(m: &Matrix, names: Option<&[String]>) -> Result<DatasetProfile> {
DatasetProfile::from_matrix(m, names)
}
pub fn profile_matrix_with_target(
m: &Matrix,
names: Option<&[String]>,
target: &str,
) -> Result<DatasetProfile> {
let profile = DatasetProfile::from_matrix(m, names)?;
Ok(profile.with_target(target))
}
pub fn profile_str_matrix(m: &StrMatrix, names: Option<&[String]>) -> Result<DatasetProfile> {
DatasetProfile::from_str_matrix(m, names)
}
pub fn profile_table(
numeric: Option<&Matrix>,
categorical: Option<&StrMatrix>,
names: &[String],
) -> Result<DatasetProfile> {
DatasetProfile::from_table(numeric, categorical, names)
}
pub fn profile_table_with_target(
numeric: Option<&Matrix>,
categorical: Option<&StrMatrix>,
names: &[String],
target: &str,
) -> Result<DatasetProfile> {
let profile = DatasetProfile::from_table(numeric, categorical, names)?;
Ok(profile.with_target(target))
}
#[cfg(feature = "csv")]
pub fn profile_csv(path: &std::path::Path, names: Option<&[String]>) -> Result<DatasetProfile> {
let table = csv::read_csv(path)?;
DatasetProfile::profile_from_csv_table_pub(&table, names)
}
#[cfg(feature = "csv")]
pub fn profile_csv_with(
path: &std::path::Path,
opts: &csv::CsvReadOptions,
names: Option<&[String]>,
) -> Result<DatasetProfile> {
let table = csv::read_csv_with(path, opts)?;
DatasetProfile::profile_from_csv_table_pub(&table, names)
}
#[cfg(feature = "csv")]
pub fn profile_csv_with_types(
path: &std::path::Path,
schema: &[ColumnType],
) -> Result<DatasetProfile> {
DatasetProfile::from_csv_with_types(path, schema)
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "csv")]
#[test]
fn profile_csv_matches_profile_str_matrix_bit_for_bit() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("parity.csv");
std::fs::write(
&path,
"age,income,city\n34,58000,Istanbul\n45,NA,Ankara\n29,45000,Izmir\n52,110000,Istanbul\n",
)
.unwrap();
let via_csv = profile_csv(&path, None).unwrap();
let table = csv::read_csv(&path).unwrap();
let names = table.column_names();
let via_matrix = profile_str_matrix(&table.rows, Some(&names)).unwrap();
assert_eq!(via_csv.columns, via_matrix.columns);
assert_eq!(via_csv.n_rows, via_matrix.n_rows);
assert_eq!(via_csv.n_columns, via_matrix.n_columns);
assert_eq!(via_csv.duplicate_rows, via_matrix.duplicate_rows);
assert_eq!(via_csv.memory_bytes, via_matrix.memory_bytes);
match (&via_csv.relationships, &via_matrix.relationships) {
(None, None) => {}
(Some(a), Some(b)) => {
assert_eq!(
a.pearson.as_ref().map(|m| m.labels.clone()),
b.pearson.as_ref().map(|m| m.labels.clone())
);
if let (Some(pa), Some(pb)) = (&a.pearson, &b.pearson) {
for (ra, rb) in pa.values.iter().zip(pb.values.iter()) {
for (va, vb) in ra.iter().zip(rb.iter()) {
assert!(va.to_bits() == vb.to_bits() || (va.is_nan() && vb.is_nan()));
}
}
}
assert_eq!(
a.cramers_v.as_ref().map(|m| m.labels.clone()),
b.cramers_v.as_ref().map(|m| m.labels.clone())
);
}
_ => panic!("relationships presence mismatch"),
}
}
#[cfg(feature = "csv")]
#[test]
fn csv_with_types_rejects_duplicate_header_names() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("dup.csv");
std::fs::write(&path, "a,a\n1,2\n3,4\n").unwrap();
let schema = [ColumnType::Numeric, ColumnType::Numeric];
let err = profile_csv_with_types(&path, &schema).unwrap_err();
assert!(
err.to_string().contains("duplicate column name 'a'"),
"{err}"
);
}
}