mtable_tibble(a = 1:3, b = a * 2, c = a + b) a b c
1 1 2 3
2 2 4 6
3 3 6 9
minitable provides a few tibble-style construction/coercion helpers – mtable_tibble(), mtable_as_tibble(), mtable_rownames_to_column(), mtable_add_row() – built entirely on data.frame()/as.data.frame(). Results are plain data frames, not tibbles. See the README for the full scope notes; this page walks through each function, including the cross-column-reference behaviour that’s the trickiest part of the mini to get right.
mtable_tibble(...) – build a data frame column by column, sequentially, so later columns can refer to earlier ones by name.mtable_as_tibble(x, ...) – coerce x to a plain data frame via as.data.frame(), preserving literal (non-syntactic) column names.mtable_rownames_to_column(.data, var) – move .data’s row names into an explicit column named var; a no-op if the row names are just the default sequential ones.mtable_add_row(.data, ...) – append a single row to .data, with the same cross-column-reference support as mtable_tibble().minitable has one internal helper, .mtable_drop_dup_list(), which mtable_tibble() and mtable_add_row() both use to resolve what a column reference means when a name is reused more than once while constructing columns in sequence (see below).
mtable_tibble(): sequential, cross-referencing constructionBuilding a data frame with data.frame() directly requires every column to already exist as a complete vector before the call – you can’t refer to a column you’re building in the same call. Like tibble::tibble(), mtable_tibble() lifts that restriction: later columns can refer to earlier ones by name, because each column expression is evaluated in order, in an environment built up from the columns already constructed:
Here b refers to a, and c refers to both a and b – neither would resolve to anything if evaluated outside the call, since a, b, and c don’t otherwise exist in this session. Getting this right took real care in the implementation: the sequential-evaluation logic lives directly inside mtable_tibble() itself, rather than in a shared helper that ... gets forwarded through. Forwarding ... to a separate function turns each argument into an opaque ..1/..2 pronoun that resolves free variables against the caller’s environment instead of the column-by-column environment being built up – which would silently break exactly this feature, evaluating b and c against whatever (unrelated) a/b might exist in the calling code, or erroring if there simply isn’t one.
Just as in tibble::tibble(), an argument with no name = is named after its own source expression, converted to a string:
This is mostly useful for quick, throwaway construction; naming columns explicitly (mtable_tibble(x = 1:3, y = sqrt(1:3))) is more readable for anything that will be used again later.
mtable_as_tibble(): coercion onlyThere’s no tibble class or special printing here – it’s just as.data.frame() with check.names = FALSE, so a literal, non-syntactic column name (like "1:3" from the previous section) survives unchanged instead of being sanitised by make.names():
The difference from calling as.data.frame() directly shows up with a name that isn’t a syntactically valid R identifier, like the "1:3" name mtable_tibble() generated automatically two sections ago:
[1] "1:3"
[1] "X1.3"
as.data.frame()’s default check.names = TRUE rewrites "1:3" into the syntactically valid "X1.3"; mtable_as_tibble() passes check.names = FALSE through instead, so the literal name survives.
mtable_rownames_to_column(): no-op on default row namesA data frame with only the default sequential row names ("1", "2", …) is returned unchanged – there’s nothing meaningful to move into a column:
[1] TRUE
Real (non-default) row names do get moved into a new column, placed first:
mtable_add_row(): the same cross-referencing supportAppending a row supports the same sequential evaluation as mtable_tibble(), so a later value in the new row can refer to an earlier one – either a column already in .data, or one being added in the same call:
a b
1 1 10
2 2 20
a b
1 1 10
2 2 20
3 3 30
Here a * 10 in the new row refers to the a = 3 just supplied in that same call, not to the existing column a in df – the most recently constructed value for a given name always wins, which is what .mtable_drop_dup_list() is for internally.