Shared conventions every function
| Argument | Meaning |
|---|---|
data | the input table / list. Never modified by reference. |
cols | columns to work on, as names or indices (c("mpg","wt"), 1:3) |
by | grouping column(s), names or indices |
out_type | "dt" data.table (default) or "df" data.frame |
path | where files go; missing folders are created |
seed | reproducible folds; your RNG stream is restored |
install.packages("mintyr") # CRAN
pak::pak("tony2015116/mintyr") # dev
library(mintyr)
library(data.table)
Import many files → one table
Read every sheet of every workbook into one data.table, with source columns excel_name / sheet_name.
sheet— indices or sheet namesskip = 1, header_rows = 2— multi-row headers joined withheader_sep; merged cells resolved viaheader_fill("auto"/"right"/"none")combine = FALSE→ named list"<file>_<sheet>"workers = 4— parallel reading for large / many fileson_error = "warn"— skip unreadable files, one warning...→readxl::read_excel()(col_types,na)
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)]
Reshape & nest wide → pieces
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")
Same reshaping, but returns a named list ("mpg_0", "mpg_1", …) — the input for split_cv() and export_list().
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))]
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
For a nested table (e.g. from w2l_nest()): one row per group × fold.
For a list of tables (e.g. from w2l_split()); wrap a single table in list().
| Argument | Effect |
|---|---|
v, repeats | folds; repeated CV adds id2 |
strata | column balanced across folds; numeric → breaks quantile bins; strata < pool merged |
materialize = FALSE | indices 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
Statistics per group × variable, fast on millions of rows.
type | Statistics |
|---|---|
"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 (addsn_miss,ci_low, …)total = TRUE— total row from all records; counts add upmin_n = 3— smaller groups keepn, other statsNAdigits = c(2, adg = 0)— per-variable roundinglabels = 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")
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")
Numeric → fixed-decimal text for tables; percentage = TRUE gives "12.50%".
Export pieces → files
- Table with
excel_name/sheet_name→ the original files & sheets (lossless round trip withimport_xlsx()) - List +
path = "out.xlsx"→ one workbook, names = sheets - List +
path = "dir"→ one workbook per element overwrite = FALSEchecks all targets before writing
dt <- import_xlsx(files)
dt <- dt[!is.na(weight)]
# same file names, same sheet names
export_xlsx(dt, path = "cleaned")
Each nested table to path/<by1>/<by2>/<col>.txt; model-object columns are skipped. Stops if by is not unique.
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()
Utilities paths & examples
p <- "D:/data/farmA/2025/pigs.xlsx" | |
| Call | Result |
|---|---|
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.
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
| Function | Old | New |
|---|---|---|
| CV, export | nest_dt, split_dt | data |
w2l_*() | cols2l | cols |
c2p_nest() | cols2bind | cols |
r2p_nest() | rows2bind, by | names_from, cols |
export_nest() | nest_cols, group_cols | cols, by |
*_cv() | splits (rsample) | train_idx / validate_idx |
top_perc() | Mean, SD, … | mean, sd, … (lower case) |