Main sorting function to order the sub-structure of a TableTree
at a particular path in the table tree.
Arguments
- tt
(
TableTree
or related class)
aTableTree
object representing a populated table.- path
(
character
)
a vector path for a position within the structure of aTableTree
. Each element represents a subsequent choice amongst the children of the previous choice.- scorefun
(
function
)
scoring function. Should accept the type of children directly under the position atpath
(eitherVTableTree
,VTableRow
, orVTableNodeInfo
, which covers both) and return a numeric value to be sorted.- decreasing
(
flag
)
whether the scores generated byscorefun
should be sorted in decreasing order. If unset (the default ofNA
), it is set toTRUE
if the generated scores are numeric andFALSE
if they are characters.- na.pos
(
string
)
what should be done with children (sub-trees/rows) withNA
scores. Defaults to"omit"
, which removes them. Other allowed values are"last"
and"first"
, which indicate whereNA
scores should be placed in the order.- .prev_path
(
character
)
internal detail, do not set manually.
Value
A TableTree
with the same structure as tt
with the exception that the requested sorting has been done
at path
.
Details
sort_at_path
, given a path, locates the (sub)table(s) described by the path (see below for handling of the "*"
wildcard). For each such subtable, it then calls scorefun
on each direct child of the table, using the resulting
scores to determine their sorted order. tt
is then modified to reflect each of these one or more sorting
operations.
In path
, a leading "root"
element will be ignored, regardless of whether this matches the object name (and thus
actual root path name) of tt
. Including "root"
in paths where it does not match the name of tt
may mask deeper
misunderstandings of how valid paths within a TableTree
object correspond to the layout used to originally declare
it, which we encourage users to avoid.
path
can include the "wildcard" "*"
as a step, which translates roughly to any node/branching element and means
that each child at that step will be separately sorted based on scorefun
and the remaining path
entries. This
can occur multiple times in a path.
A list of valid (non-wildcard) paths can be seen in the path
column of the data.frame
created by
formatters::make_row_df()
with the visible_only
argument set to FALSE
. It can also be inferred from the
summary given by table_structure()
.
Note that sorting needs a deeper understanding of table structure in rtables
. Please consider reading the related
vignette
(Sorting and Pruning)
and explore table structure with useful functions like table_structure()
and row_paths_summary()
. It is also
very important to understand the difference between "content" rows and "data" rows. The first one analyzes and
describes the split variable generally and is generated with summarize_row_groups()
, while the second one is
commonly produced by calling one of the various analyze()
instances.
Built-in score functions are cont_n_allcols()
and cont_n_onecol()
. They are both working with content rows
(coming from summarize_row_groups()
) while a custom score function needs to be used on DataRow
s. Here, some
useful descriptor and accessor functions (coming from related vignette):
cell_values()
- Retrieves a named list of aTableRow
orTableTree
object's values.formatters::obj_name()
- Retrieves the name of an object. Note this can differ from the label that is displayed (if any is) when printing.formatters::obj_label()
- Retrieves the display label of an object. Note this can differ from the name that appears in the path.content_table()
- Retrieves aTableTree
object's content table (which contains its summary rows).tree_children()
- Retrieves aTableTree
object's direct children (either subtables, rows or possibly a mix thereof, though that should not happen in practice).
See also
Score functions
cont_n_allcols()
andcont_n_onecol()
.formatters::make_row_df()
andtable_structure()
for pathing information.tt_at_path()
to select a table's (sub)structure at a given path.
Examples
# Creating a table to sort
# Function that gives two statistics per table-tree "leaf"
more_analysis_fnc <- function(x) {
in_rows(
"median" = median(x),
"mean" = mean(x),
.formats = "xx.x"
)
}
# Main layout of the table
raw_lyt <- basic_table() %>%
split_cols_by("ARM") %>%
split_rows_by(
"RACE",
split_fun = drop_and_remove_levels("WHITE") # dropping WHITE levels
) %>%
summarize_row_groups() %>%
split_rows_by("STRATA1") %>%
summarize_row_groups() %>%
analyze("AGE", afun = more_analysis_fnc)
# Creating the table and pruning empty and NAs
tbl <- build_table(raw_lyt, DM) %>%
prune_table()
# Peek at the table structure to understand how it is built
table_structure(tbl)
#> [TableTree] RACE
#> [TableTree] ASIAN [cont: 1 x 3]
#> [TableTree] STRATA1
#> [TableTree] A [cont: 1 x 3]
#> [ElementaryTable] AGE (2 x 3)
#> [TableTree] B [cont: 1 x 3]
#> [ElementaryTable] AGE (2 x 3)
#> [TableTree] C [cont: 1 x 3]
#> [ElementaryTable] AGE (2 x 3)
#> [TableTree] BLACK OR AFRICAN AMERICAN [cont: 1 x 3]
#> [TableTree] STRATA1
#> [TableTree] A [cont: 1 x 3]
#> [ElementaryTable] AGE (2 x 3)
#> [TableTree] B [cont: 1 x 3]
#> [ElementaryTable] AGE (2 x 3)
#> [TableTree] C [cont: 1 x 3]
#> [ElementaryTable] AGE (2 x 3)
# Sorting only ASIAN sub-table, or, in other words, sorting STRATA elements for
# the ASIAN group/row-split. This uses content_table() accessor function as it
# is a "ContentRow". In this case, we also base our sorting only on the second column.
sort_at_path(tbl, c("ASIAN", "STRATA1"), cont_n_onecol(2))
#> A: Drug X B: Placebo C: Combination
#> ————————————————————————————————————————————————————————————————————
#> ASIAN 79 (65.3%) 68 (64.2%) 84 (65.1%)
#> B 24 (19.8%) 29 (27.4%) 22 (17.1%)
#> median 32.5 32.0 34.0
#> mean 34.1 31.6 34.7
#> A 27 (22.3%) 20 (18.9%) 31 (24.0%)
#> median 30.0 33.0 36.0
#> mean 32.2 33.9 36.8
#> C 28 (23.1%) 19 (17.9%) 31 (24.0%)
#> median 36.5 34.0 33.0
#> mean 36.2 33.0 32.4
#> BLACK OR AFRICAN AMERICAN 28 (23.1%) 24 (22.6%) 27 (20.9%)
#> A 6 (5.0%) 7 (6.6%) 8 (6.2%)
#> median 32.0 29.0 32.5
#> mean 31.5 28.6 33.6
#> B 10 (8.3%) 6 (5.7%) 12 (9.3%)
#> median 33.0 30.0 33.5
#> mean 35.6 30.8 33.7
#> C 12 (9.9%) 11 (10.4%) 7 (5.4%)
#> median 33.0 36.0 32.0
#> mean 35.5 34.2 35.0
# Custom scoring function that is working on "DataRow"s
scorefun <- function(tt) {
# Here we could use browser()
sum(unlist(row_values(tt))) # Different accessor function
}
# Sorting mean and median for all the AGE leaves!
sort_at_path(tbl, c("RACE", "*", "STRATA1", "*", "AGE"), scorefun)
#> A: Drug X B: Placebo C: Combination
#> ————————————————————————————————————————————————————————————————————
#> ASIAN 79 (65.3%) 68 (64.2%) 84 (65.1%)
#> A 27 (22.3%) 20 (18.9%) 31 (24.0%)
#> mean 32.2 33.9 36.8
#> median 30.0 33.0 36.0
#> B 24 (19.8%) 29 (27.4%) 22 (17.1%)
#> mean 34.1 31.6 34.7
#> median 32.5 32.0 34.0
#> C 28 (23.1%) 19 (17.9%) 31 (24.0%)
#> median 36.5 34.0 33.0
#> mean 36.2 33.0 32.4
#> BLACK OR AFRICAN AMERICAN 28 (23.1%) 24 (22.6%) 27 (20.9%)
#> A 6 (5.0%) 7 (6.6%) 8 (6.2%)
#> mean 31.5 28.6 33.6
#> median 32.0 29.0 32.5
#> B 10 (8.3%) 6 (5.7%) 12 (9.3%)
#> mean 35.6 30.8 33.7
#> median 33.0 30.0 33.5
#> C 12 (9.9%) 11 (10.4%) 7 (5.4%)
#> mean 35.5 34.2 35.0
#> median 33.0 36.0 32.0