1.6.14 Data sources
Source: "glmnet/examples/13-data-sources.rkt"
This section fits one model to one dataset, which arrives through each data source of Data in turn: R’s glmnet(as.matrix(mtcars[, c("wt", "hp", "qsec")]), mtcars$mpg), the lasso path of fuel economy on a car’s weight, horsepower and quarter-mile time. The data are R’s mtcars, which glmnet/datasets ships as a CSV file and provides as a table. Every source holds the same doubles and every conversion keeps them, so each gives the same design matrix, names included, and the same path, R’s.
1.6.14.1 A table
The predictors by name, the file the table comes from, and a column of the table by name:
> (require glmnet/datasets glmnet/data/nested glmnet/data/csv glmnet/data/math glmnet/data/polars (only-in math/matrix build-matrix ->col-matrix matrix-shape) (only-in polars read-csv)) > (define predictors '("wt" "hp" "qsec")) > (define file (collection-file-path "mtcars.csv" "glmnet" "datasets")) > (define (column name) (cdr (assoc name mtcars)))
A table’s numeric columns are a design matrix, and its response column, a vector, is a response as it is. The path has R’s sequence of λ, and R’s coef(fit, s = 0.5):
> (define from-table (table->design-matrix mtcars predictors)) > (define mpg (column "mpg")) > (define fit (elnet-path from-table mpg)) > (vector-length (glmnet-path-lambda fit)) 58
> (coef fit #:lambda 0.5)
'#(33.16562014425745
-3.6829279730390896
-0.02385276160227977
0.12733703169896884)
1.6.14.2 Lists and vectors
The table’s columns are vectors, which nested->design-matrix takes one per column:
> (define from-nested (nested->design-matrix (map column predictors) #:by 'columns #:column-names predictors)) > (equal? from-nested from-table) #t
1.6.14.3 A CSV file
csv-file->table reads the file into a table of vector columns:
> (define cars (csv-file->table file)) > (define from-csv (table->design-matrix cars predictors)) > (equal? from-csv from-table) #t
> (equal? (elnet-path from-csv (cdr (assoc "mpg" cars))) fit) #t
1.6.14.4 A matrix
A math/matrix matrix has the observations as its rows, and the response can be a column matrix:
> (define M (build-matrix 32 3 (lambda (i j) (vector-ref (column (list-ref predictors j)) i)))) > (matrix-shape M)
32
3
> (define from-math (matrix->design-matrix M #:column-names predictors)) > (equal? from-math from-table) #t
> (equal? (elnet-path from-math (array->response (->col-matrix mpg))) fit) #t
1.6.14.5 A Polars dataframe
Polars reads the file itself, and the predictors leave it in one copy:
> (define df (read-csv file)) > (define from-polars (polars->design-matrix df predictors)) > (equal? from-polars from-table) #t
> (equal? (elnet-path from-polars (polars->response df "mpg")) fit) #t
1.6.14.6 Formulas, and back
Each source that gives a table, the dataset, the CSV file’s table and the dataframe through polars->table, fits the same formula model:
> (define (fit-formula table) (coef (formula-fit (mpg . ~ . wt + hp + qsec) table #:lambda 0.5))) > (fit-formula mtcars)
'(("(Intercept)" . 33.11848756050567)
("wt" . -3.689045302372365)
("hp" . -0.02373045877112981)
("qsec" . 0.1300752214884471))
> (equal? (fit-formula cars) (fit-formula mtcars)) #t
> (equal? (fit-formula (polars->table df)) (fit-formula mtcars)) #t
The design matrix converts back to each of them. A design matrix with column names is a table, which table->csv writes:
> (define first-cars (design-matrix-select-rows from-table '(0 1 2))) > (design-matrix->nested first-cars) '((2.62 110.0 16.46) (2.875 110.0 17.02) (2.32 93.0 18.61))
> (design-matrix->matrix first-cars) (flarray #[#[2.62 110.0 16.46] #[2.875 110.0 17.02] #[2.32 93.0 18.61]])
> (design-matrix->polars first-cars)
shape: (3, 3)
┌───────┬───────┬───────┐
│ wt ┆ hp ┆ qsec │
│ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 │
╞═══════╪═══════╪═══════╡
│ 2.62 ┆ 110.0 ┆ 16.46 │
│ 2.875 ┆ 110.0 ┆ 17.02 │
│ 2.32 ┆ 93.0 ┆ 18.61 │
└───────┴───────┴───────┘
> (table->csv first-cars)
wt,hp,qsec
2.62,110,16.46
2.875,110,17.02
2.32,93,18.61