Hesper.Data.DataFrame — minimal CSV-backed data analysis primitives #
This module is the Option A MVP for tutorial Ch11: just enough of a DataFrame API to port the Sabela CaliforniaHousing example to Lean.
Scope (intentionally small):
- Schema-on-read CSV loading with
Float/String/Option Float. - Row-level selection (
take,randomSplit). - Column-level projection (
select,exclude,columnNames,dimensions). - Missing-value imputation (
impute). - Derived columns (
derive,deriveMany) computed from scalars per row. - Min-max normalisation across all numeric columns (
normalizeFeatures). - Markdown pretty-printer for Jupyter (
toMarkdown). - GPU upload (
toTensor) producing aFloat32Arrayready for matmul.
Out of scope (Option B will add it on top):
- Typed column references via Lean macros.
Columnalgebra (+ - * /lifted to columns).- GroupBy / Join / Arrow interop.
The API is shaped after
DataHaskell's dataframe (the
library Sabela wraps), so users coming from that world should find it
familiar. Naming choices follow Sabela where they map cleanly to Lean.
Acknowledgements #
The data-analysis surface (column-oriented design, impute / derive / randomSplit / normalizeFeatures helpers, min-max normalisation
choice, walk-through structure of the California Housing example)
follows
DataHaskell's dataframe
and
Sabela's port to Hasktorch.
Implementation is fresh Lean 4 code; semantics, normalisation policy
and the example layout are adapted from those projects. Thanks to
their authors.
Instances For
Equations
Equations
- One or more equations did not get rendered due to their size.
- Hesper.Data.instReprValue.repr Hesper.Data.Value.missing prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Hesper.Data.Value.missing")).group prec✝
Instances For
Equations
- Hesper.Data.instReprValue = { reprPrec := Hesper.Data.instReprValue.repr }
Project to String?. Numerics are stringified.
Equations
Instances For
Inferred column type. optF64 means the column contains at least
one NA — used to format header cells like the Haskell Maybe Double.
- f64 : ColumnType
- optF64 : ColumnType
- text : ColumnType
Instances For
Equations
Equations
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Hesper.Data.instBEqColumnType.beq x✝ y✝ = (x✝.ctorIdx == y✝.ctorIdx)
Instances For
Equations
Equations
- Hesper.Data.ColumnType.f64.label = "Float"
- Hesper.Data.ColumnType.optF64.label = "Float?"
- Hesper.Data.ColumnType.text.label = "String"
Instances For
A row-oriented data frame. All rows have the same length as
columns; cell (row, col) is rows[row]![col]!.
The row-oriented layout makes derive and impute cheap to express
(one closure per row) at the cost of a strided access pattern for
column reductions. At the scale Ch11 needs (≤ 20k rows × 11 cols)
this is irrelevant; a column-oriented redesign is left for Option B.
- schema : Array ColumnType
Instances For
Equations
Equations
Instances For
Equations
- df.columnNames = df.columns
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
All Float values in a column, skipping NAs / non-numeric.
Equations
- df.numericColumn name = Array.filterMap Hesper.Data.Value.toFloat? (df.column name)
Instances For
Drop the named columns.
Equations
- Hesper.Data.DataFrame.exclude cols df = Hesper.Data.DataFrame.select (Array.filter (fun (x : String) => !cols.contains x) df.columns) df
Instances For
Minimum of a numeric column, ignoring NAs.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Maximum of a numeric column, ignoring NAs.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Append a new column computed from each row. The whole Array Value
is passed to the closure so it can reference any other column by
index/name. The new column's type is inferred from the first
non-missing cell.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Helper: derive a Float column from a function on the named
columns of each row. Looks up the name once.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Min-max normalise every numeric column into [0, 1]. Constant
columns (max == min) are left at 0. Mirrors Sabela's
normalizeFeatures helper.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Random split #
Split into (train, test) with frac of rows going to train. Order
is randomised with seed for reproducibility, matching Sabela's
D.randomSplit (mkStdGen seed) frac.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Pretty-printing #
GFM-style markdown table with header type annotations like
Sabela's total_rooms<br>Double. Suitable for displayMarkdown
in a Jupyter cell.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Like toMarkdown but caps the row count. Handy in cells where a
20k-row dump would overwhelm Jupyter.
Equations
Instances For
HTML table renderer. Use this with xeus-lean's #html command to
get a real <table> (markdown round-trip via IO.println only
yields raw text in #eval cells). Column headers include the
inferred type, matching toMarkdown.
Equations
- One or more equations did not get rendered due to their size.
Instances For
CSV loader (minimal) #
Local float parser #
`Hesper.Training.ParseFloat.parseFloat` works on older Lean — its
`String.Pos.mk ⟨...⟩` and `String.trim` usages don't survive the
4.28 API churn. Re-implement a small parser inline that handles
California-Housing-style decimals + scientific notation.
Read a CSV file with a header row. Type inference: a column is
text if any non-empty cell fails to parse as Float, optF64 if
all non-empty cells are floats but at least one cell is missing,
f64 otherwise. Lines are split on \n (also handles \r\n).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Tensor export #
Flatten the numeric columns of df into a row-major Float32Array
suitable for upload as a feature matrix. Non-numeric and missing
cells are encoded as 0.0 — call impute first to control that
behaviour. The returned shape is (numRows, numNumericCols).
Equations
- One or more equations did not get rendered due to their size.