mintyr logo

mintyr cheat sheet v0.2.1

Grouped and nested data pipelines built on data.table: import many files into one table, reshape and nest by trait × group, cross-validate and summarise every group, and write every piece back to its own file.

Files
.xlsx · .csv · .txt
1 · Import
import_xlsx()
import_csv()
2 · Reshape & nest
w2l_nest() w2l_split()
c2p_nest() r2p_nest()
3 · Cross-validate
nest_cv()
split_cv()
3 · Summarise
desc_stats() top_perc()
format_digits()
4 · Export
export_xlsx() export_nest()
export_list()

Shared conventions every function

ArgumentMeaning
datathe input table / list. Never modified by reference.
colscolumns to work on, as names or indices (c("mpg","wt"), 1:3)
bygrouping column(s), names or indices
out_type"dt" data.table (default) or "df" data.frame
pathwhere files go; missing folders are created
seedreproducible folds; your RNG stream is restored
install.packages("mintyr")       # CRAN
pak::pak("tony2015116/mintyr")   # dev
library(mintyr)
library(data.table)
No silent data loss: if two outputs would land on the same file, mintyr stops instead of overwriting.

Import many files → one table

import_xlsx(file, combine = TRUE, sheet = NULL, skip = 0, header_rows = 1, header_sep = "_", header_fill = "auto", file_col = "excel_name", sheet_col = "sheet_name", path_col = NULL, workers = 1, verbose = FALSE, on_error = "stop", ...)

Read every sheet of every workbook into one data.table, with source columns excel_name / sheet_name.

  • sheet — indices or sheet names
  • skip = 1, header_rows = 2 — multi-row headers joined with header_sep; merged cells resolved via header_fill ("auto" / "right" / "none")
  • combine = FALSE → named list "<file>_<sheet>"
  • workers = 4 — parallel reading for large / many files
  • on_error = "warn" — skip unreadable files, one warning
  • ... → readxl::read_excel() (col_types, na)
import_csv(file, combine = TRUE, file_col = "_file", path_col = NULL, full_path = FALSE, keep_ext = FALSE, ...)

Read many CSV / TXT files with fread(); ... goes to fread() (select, na.strings, nThread).

files <- list.files("raw", "\\.xlsx$",
                    full.names = TRUE,
                    recursive = TRUE)
dt <- import_xlsx(files, skip = 1,
                  header_rows = 2,
                  path_col = "file_path")
# raw/<farm>/<year>/file.xlsx  ->  columns
dt[, farm := get_path_info(file_path, n = -3)]
dt[, year := get_path_info(file_path, n = -2)]
New in 0.2.1: a column empty in one sheet takes its type from the others; genuinely mixed types are combined as text with one warning. Types are guessed from all rows.

Reshape & nest wide → pieces

w2l_nest(data, cols = NULL, by = NULL, out_type = "dt")

Wide → long, then nest by trait (name) and by into a data list-column. cols = NULL + by: nest without melting.

nested <- w2l_nest(mtcars,
                   cols = c("mpg", "qsec"),
                   by = "am")
w2l_split(data, cols = NULL, by = NULL, out_type = "dt", sep = "_")

Same reshaping, but returns a named list ("mpg_0", "mpg_1", …) — the input for split_cv() and export_list().

c2p_nest(data, cols, by = NULL, pairs_n = 2, sep = "-", out_type = "dt")

Every pair (or triple: pairs_n = 3) of variables, renamed value1, value2, … so one function fits all pairs.

pairs <- c2p_nest(mtcars,
                  cols = c("mpg", "hp", "wt"),
                  by = "am")
pairs[, r := sapply(data, function(d)
  cor(d$value1, d$value2))]
r2p_nest(data, names_from, cols, out_type = "dt", id = NULL)

Same trait across the levels of names_from, side by side and aligned by id (e.g. G×E correlations). Stops if id + names_from are not unique.

r2p_nest(growth, names_from = "farm",
         cols = c("adg", "bf"), id = "animal")

Cross-validation k-fold inside every group

nest_cv(data, v = 10, repeats = 1, strata = NULL, breaks = 4, pool = 0.1, seed = NULL, materialize = TRUE, out_type = "dt")

For a nested table (e.g. from w2l_nest()): one row per group × fold.

split_cv(data, v = 10, repeats = 1, strata = NULL, breaks = 4, pool = 0.1, seed = NULL, materialize = TRUE, out_type = "dt")

For a list of tables (e.g. from w2l_split()); wrap a single table in list().

ArgumentEffect
v, repeatsfolds; repeated CV adds id2
stratacolumn balanced across folds; numeric → breaks quantile bins; strata < pool merged
materialize = FALSEindices only — far less memory
out_type = "df"subsets as data.frame (ASReml-R)

Returns id (Fold1… or Repeat1…), id2, train_idx, validate_idx, and train / validate subsets.

cv <- nest_cv(nested, v = 4, seed = 2026)
cv[, r := mapply(function(tr, va) {
  fit <- lm(value ~ wt + hp, data = tr)
  cor(predict(fit, va), va$value)
}, train, validate)]
cv[, .(mean_r = mean(r)), by = .(name, am)]

Descriptive statistics report-ready

desc_stats(data, cols = NULL, by = NULL, type = "common", stats = NULL, total = FALSE, total_label = "Total", min_n = 1, probs = c(0, .25, .5, .75, 1), conf_level = 0.95, na_rm = TRUE, digits = NULL, fmt = NULL, labels = NULL, shape = "long", sep = "_", out_type = "dt")

Statistics per group × variable, fast on millions of rows.

typeStatistics
"common"n min max median iqr mean sd se ci
"full"+ q1 q3 mad cv skew kurt
"mean_sd" / "mean_se" / "mean_ci"n, mean and sd / se / ci_low, ci_high
"median_iqr" / "median_mad"n, median and iqr / mad
"robust" / "five_number"n median iqr / n min q1 median q3 max
"quantile"n and probs → q5, q2.5, …
  • stats = c("n", "mean", "cv") — pick any, in order (adds n_miss, ci_low, …)
  • total = TRUE — total row from all records; counts add up
  • min_n = 3 — smaller groups keep n, other stats NA
  • digits = c(2, adg = 0) — per-variable rounding
  • labels = c(adg = "ADG (g)") · shape = "wide" for report tables

fmt templates: {mean} {sd:1} (1 decimal) {cv:1%} (percent) {q2.5} (percentile).

desc_stats(mtcars, cols = c("mpg", "wt"),
           by = "cyl", fmt = "{mean} ± {sd}",
           total = TRUE, shape = "wide")
# count table with row + column totals
desc_stats(iris, by = "Species", stats = "n",
           total = TRUE, shape = "wide")
top_perc(data, perc, cols, by = NULL, keep_data = FALSE, stats = c("n", "min", "max", "mean", "median", "sd", "se", "cv"))

Statistics of the top (perc = 0.1) or bottom (-0.1) X% per variable & group; several perc at once. keep_data = TRUE also returns the rows ($stat, $data).

top_perc(iris, perc = c(0.1, -0.1),
         cols = "Petal.Width", by = "Species")
format_digits(data, cols = NULL, digits = 2, percentage = FALSE, nan_as_na = FALSE)

Numeric → fixed-decimal text for tables; percentage = TRUE gives "12.50%".

Export pieces → files

export_xlsx(data, path, file_col = "excel_name", sheet_col = "sheet_name", sheet_name = "Sheet1", drop_cols = TRUE, overwrite = TRUE, verbose = FALSE)
  • Table with excel_name / sheet_name → the original files & sheets (lossless round trip with import_xlsx())
  • List + path = "out.xlsx" → one workbook, names = sheets
  • List + path = "dir" → one workbook per element
  • overwrite = FALSE checks all targets before writing
dt <- import_xlsx(files)
dt <- dt[!is.na(weight)]
# same file names, same sheet names
export_xlsx(dt, path = "cleaned")
export_nest(data, by = NULL, cols = NULL, path = tempdir(), file_type = "txt", na = "NA", quote = FALSE, ...)

Each nested table to path/<by1>/<by2>/<col>.txt; model-object columns are skipped. Stops if by is not unique.

export_list(data, path = tempdir(), file_type = "txt", na = "NA", quote = FALSE, ...)

Each list element to its own file; names containing / become sub-folders.

# HIBLUP: header, NA
export_nest(nested, path = "hiblup_runs")
# DMU: numeric missing code, no header
export_nest(nested, path = "dmu_runs",
            na = "-9999",
            col.names = FALSE)  # to fwrite()
All three return the written file paths invisibly.

Utilities paths & examples

get_path_info(path, n = NULL, rm_extension = TRUE, rm_path = TRUE)
p <- "D:/data/farmA/2025/pigs.xlsx"
CallResult
get_path_info(p)"pigs"
get_path_info(p, rm_extension = FALSE)"pigs.xlsx"
get_path_info(p, n = 1)"data" (drive letter is not a segment)
get_path_info(p, n = -3)"farmA"
get_path_info(p, n = c(-3, -2))"farmA/2025"

Mixed / and \ separators are fine; out-of-range segments give NA.

mintyr_examples(pattern = NULL)  ·  mintyr_example(path = NULL)

List / locate the example files shipped with the package.

mintyr_examples("xlsx")
import_xlsx(mintyr_example("xlsx_test1.xlsx"))

Upgrading from 0.1.x old names removed

FunctionOldNew
CV, exportnest_dt, split_dtdata
w2l_*()cols2lcols
c2p_nest()cols2bindcols
r2p_nest()rows2bind, bynames_from, cols
export_nest()nest_cols, group_colscols, by
*_cv()splits (rsample)train_idx / validate_idx
top_perc()Mean, SD, …mean, sd, … (lower case)
Old argument names now fail with unused argument. Full list in NEWS.