Skip to content

Commit bc14bb9

Browse files
gmbeckergithub-actions[bot]shajoezhuTazovsky
authored
implement optional 'sas' rounding, pass round_type and na_str to fmt fun (#337)
addresses #336 and #319 --------- Signed-off-by: Joe Zhu <sha.joe.zhu@gmail.com> Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Joe Zhu <sha.joe.zhu@gmail.com> Co-authored-by: Kamil <tazzpl@gmail.com> Co-authored-by: shajoezhu <3692541+shajoezhu@users.noreply.github.com>
1 parent fcc4fb8 commit bc14bb9

19 files changed

+469
-133
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## formatters 0.5.10.9002
22
* Fixed a bug in `mform_handle_newlines` that caused string matrix column names to be removed. This prevented paginated listing key column info from being repeated when vertically spanning multiple pages.
33
* Minor bug fix with the `paginate` argument in the `export_as_rtf` function.
4+
* Add `round_type` argument to indicate iec (default) or sas (nearest value, 5 goes up) rounding to all formatting machinery
5+
* Added support for new 2- and 3-d formats
46

57
## formatters 0.5.10
68
* Fixed a bug in `mf_update_cinfo` causing an error when `export_as_txt` was applied to empty listings.

R/format_value.R

Lines changed: 171 additions & 71 deletions
Large diffs are not rendered by default.

R/generics.R

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#' (like [`MatrixPrintForm`]).
1111
#'
1212
#' @inheritParams open_font_dev
13+
#' @inheritParams format_value
1314
#' @param tt (`ANY`)\cr object representing the table-like object to be summarized.
1415
#' @param visible_only (`flag`)\cr should only visible aspects of the table structure be reflected
1516
#' in this summary. Defaults to `TRUE`. May not be supported by all methods.
@@ -66,7 +67,8 @@ setGeneric("make_row_df", function(tt, colwidths = NULL, visible_only = TRUE,
6667
nsibs = NA_integer_,
6768
max_width = NULL,
6869
fontspec = font_spec(),
69-
col_gap = 3L) {
70+
col_gap = 3L,
71+
round_type = c("iec", "sas")) {
7072
standardGeneric("make_row_df")
7173
})
7274

@@ -82,7 +84,8 @@ setMethod("make_row_df", "MatrixPrintForm", function(tt, colwidths = NULL, visib
8284
nsibs = NA_integer_,
8385
max_width = NULL,
8486
fontspec = font_spec(),
85-
col_gap = mf_colgap(tt) %||% 3L) {
87+
col_gap = mf_colgap(tt) %||% 3L,
88+
round_type = c("iec", "sas")) {
8689
msg <- paste0(
8790
"make_row_df can be used only on {rtables} table objects, and not on `matrix_form`-",
8891
"generated objects (MatrixPrintForm)."
@@ -96,6 +99,7 @@ setMethod("make_row_df", "MatrixPrintForm", function(tt, colwidths = NULL, visib
9699
#' it is useful to map the `rtable` to an in-between state with the formatted cells in a matrix form.
97100
#'
98101
#' @inheritParams make_row_df
102+
#' @inheritParams format_value
99103
#' @param obj (`ANY`)\cr object to be transformed into a ready-to-render form (a [`MatrixPrintForm`] object).
100104
#' @param indent_rownames (`flag`)\cr if `TRUE`, the row names column in the `strings` matrix of `obj`
101105
#' will have indented row names (strings pre-fixed).
@@ -122,7 +126,8 @@ setGeneric("matrix_form", function(obj,
122126
expand_newlines = TRUE,
123127
indent_size = 2,
124128
fontspec = NULL,
125-
col_gap = NULL) {
129+
col_gap = NULL,
130+
round_type = c("iec", "sas")) {
126131
standardGeneric("matrix_form")
127132
})
128133

@@ -134,7 +139,8 @@ setMethod("matrix_form", "MatrixPrintForm", function(obj,
134139
expand_newlines = TRUE,
135140
indent_size = 2,
136141
fontspec = NULL,
137-
col_gap = NULL) {
142+
col_gap = NULL,
143+
round_type = c("iec", "sas")) {
138144
if (!is.null(fontspec)) {
139145
mf_fontspec(obj) <- fontspec
140146
}

R/mpf_exporters.R

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ export_as_txt <- function(x,
5959
page_break = "\\s\\n",
6060
page_num = default_page_number(),
6161
fontspec = font_spec(font_family, font_size, lineheight),
62-
col_gap = 3) {
62+
col_gap = 3,
63+
round_type = c("iec", "sas")) {
6364
# Processing lists of tables or listings
6465
if (.is_list_of_tables_or_listings(x)) {
6566
if (isFALSE(paginate)) {
@@ -94,11 +95,20 @@ export_as_txt <- function(x,
9495
rep_cols = rep_cols,
9596
page_num = page_num,
9697
fontspec = fontspec,
97-
col_gap = col_gap
98+
col_gap = col_gap,
99+
round_type = round_type
98100
)
99101
} else {
100-
mf <- matrix_form(x, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec, col_gap = col_gap)
101-
mf_col_widths(mf) <- colwidths %||% propose_column_widths(mf, fontspec = fontspec)
102+
mf <- matrix_form(
103+
x,
104+
TRUE,
105+
TRUE,
106+
indent_size = indent_size,
107+
fontspec = fontspec,
108+
col_gap = col_gap,
109+
round_type = round_type
110+
)
111+
mf_col_widths(mf) <- colwidths %||% propose_column_widths(mf, fontspec = fontspec, round_type = round_type)
102112
pages <- list(mf)
103113
}
104114

@@ -176,11 +186,11 @@ prep_header_line <- function(mf, i) {
176186
## )
177187
## }
178188

179-
mpf_to_dfbody <- function(mpf, colwidths, fontspec) {
180-
mf <- matrix_form(mpf, indent_rownames = TRUE, fontspec = fontspec)
189+
mpf_to_dfbody <- function(mpf, colwidths, fontspec, round_type = c("iec", "sas")) {
190+
mf <- matrix_form(mpf, indent_rownames = TRUE, fontspec = fontspec, round_type = round_type)
181191
nlr <- mf_nlheader(mf)
182192
if (is.null(colwidths)) {
183-
colwidths <- propose_column_widths(mf, fontspec = fontspec)
193+
colwidths <- propose_column_widths(mf, fontspec = fontspec, round_type = round_type)
184194
}
185195
mf$strings[1:nlr, 1] <- ifelse(nzchar(mf$strings[1:nlr, 1, drop = TRUE]),
186196
mf$strings[1:nlr, 1, drop = TRUE],
@@ -222,24 +232,25 @@ mpf_to_rtf <- function(mpf,
222232
font_size = 8,
223233
lineheight = 1,
224234
fontspec = font_spec(font_family, font_size, lineheight),
235+
round_type = round_type,
225236
...) {
226237
if (!requireNamespace("r2rtf")) {
227238
stop("RTF export requires the 'r2rtf' package, please install it.")
228239
}
229240
if (fontspec$family != "Courier") {
230241
stop("Experimental RTF export does not currently support fonts other than Courier")
231242
}
232-
mpf <- matrix_form(mpf, indent_rownames = TRUE, fontspec = fontspec)
243+
mpf <- matrix_form(mpf, indent_rownames = TRUE, fontspec = fontspec, round_type = round_type)
233244
nlr <- mf_nlheader(mpf)
234245
if (is.null(colwidths)) {
235-
colwidths <- propose_column_widths(mpf, fontspec = fontspec)
246+
colwidths <- propose_column_widths(mpf, fontspec = fontspec, round_type = round_type)
236247
}
237248
mpf$strings[1:nlr, 1] <- ifelse(nzchar(mpf$strings[1:nlr, 1, drop = TRUE]),
238249
mpf$strings[1:nlr, 1, drop = TRUE],
239250
strrep(" ", colwidths)
240251
)
241252

242-
myfakedf <- mpf_to_dfbody(mpf, colwidths, fontspec = fontspec)
253+
myfakedf <- mpf_to_dfbody(mpf, colwidths, fontspec = fontspec, round_type = round_type)
243254

244255
rtfpg <- r2rtf::rtf_page(myfakedf,
245256
width = pg_width,
@@ -551,7 +562,8 @@ export_as_pdf <- function(x,
551562
max_width = NULL,
552563
colwidths = NULL,
553564
fontspec = font_spec(font_family, font_size, lineheight),
554-
ttype_ok = FALSE) {
565+
ttype_ok = FALSE,
566+
round_type = c("iec", "sas")) {
555567
## this has to happen at the very beginning before the first use of fontspec
556568
## which happens in the default value of colwidths. yay lazy evaluation...
557569
if (missing(font_size) && !missing(fontsize)) {
@@ -627,10 +639,11 @@ export_as_pdf <- function(x,
627639
indent_size = indent_size,
628640
verbose = FALSE,
629641
rep_cols = rep_cols,
630-
page_num = page_num
642+
page_num = page_num,
643+
round_type = round_type
631644
)
632645
} else {
633-
mf <- matrix_form(x, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec)
646+
mf <- matrix_form(x, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec, round_type = round_type)
634647
mf_col_widths(mf) <- colwidths %||% propose_column_widths(mf, fontspec = fontspec)
635648
tbls <- list(mf)
636649
}

R/pagination.R

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ pag_indices_inner <- function(pagdf,
568568
#'
569569
#' @inheritParams pag_indices_inner
570570
#' @inheritParams open_font_dev
571+
#' @inheritParams format_value
571572
#' @param obj (`ANY`)\cr object to be paginated. Must have a [matrix_form()] method.
572573
#' @param cpp (`numeric(1)`)\cr number of characters per page (width).
573574
#' @param colwidths (`numeric`)\cr vector of column widths (in characters) for use in vertical pagination.
@@ -588,11 +589,12 @@ vert_pag_indices <- function(obj,
588589
verbose = FALSE,
589590
rep_cols = 0L,
590591
fontspec,
591-
nosplitin = character()) {
592+
nosplitin = character(),
593+
round_type = c("iec", "sas")) {
592594
if (is.list(nosplitin)) {
593595
nosplitin <- nosplitin[["cols"]]
594596
}
595-
mf <- matrix_form(obj, indent_rownames = TRUE, fontspec = fontspec)
597+
mf <- matrix_form(obj, indent_rownames = TRUE, fontspec = fontspec, round_type = round_type)
596598
clwds <- colwidths %||% propose_column_widths(mf, fontspec = fontspec)
597599
if (is.null(mf_cinfo(mf))) { ## like always, ugh.
598600
mf <- mpf_infer_cinfo(mf, colwidths = clwds, rep_cols = rep_cols, fontspec = fontspec)
@@ -998,6 +1000,7 @@ paginate_indices <- function(obj,
9981000
rep_cols = num_rep_cols(obj),
9991001
col_gap = 3,
10001002
fontspec = font_spec(font_family, font_size, lineheight),
1003+
round_type = c("iec", "sas"),
10011004
verbose = FALSE) {
10021005
## this preserves backwards compatibility
10031006
## could start deprecation cycle of char input
@@ -1031,9 +1034,9 @@ paginate_indices <- function(obj,
10311034

10321035
## order is annoying here, since we won't actually need the mpf if
10331036
## we run into forced pagination, but life is short and this should work fine.
1034-
mpf <- matrix_form(obj, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec)
1037+
mpf <- matrix_form(obj, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec, round_type = round_type)
10351038
if (is.null(colwidths)) {
1036-
colwidths <- mf_col_widths(mpf) %||% propose_column_widths(mpf, fontspec = fontspec)
1039+
colwidths <- mf_col_widths(mpf) %||% propose_column_widths(mpf, fontspec = fontspec, round_type = round_type)
10371040
} else {
10381041
mf_col_widths(mpf) <- colwidths
10391042
}
@@ -1139,6 +1142,7 @@ paginate_indices <- function(obj,
11391142
cpp = pg_size_spec$cpp, colwidths = colwidths,
11401143
rep_cols = rep_cols, fontspec = fontspec,
11411144
nosplitin = nosplitin[["cols"]],
1145+
round_type = round_type,
11421146
verbose = verbose
11431147
)
11441148
}
@@ -1176,6 +1180,7 @@ paginate_to_mpfs <- function(obj,
11761180
# col_gap = 3, # this could be change in default - breaking change
11771181
col_gap = 3,
11781182
fontspec = font_spec(font_family, font_size, lineheight),
1183+
round_type = c("iec", "sas"),
11791184
verbose = FALSE) {
11801185
newdev <- open_font_dev(fontspec)
11811186
if (newdev) {
@@ -1216,7 +1221,7 @@ paginate_to_mpfs <- function(obj,
12161221
prov_footer(obj) <- c(prov_footer(obj), page_num)
12171222
}
12181223

1219-
mpf <- matrix_form(obj, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec)
1224+
mpf <- matrix_form(obj, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec, round_type = round_type)
12201225
# For listings, keycols are mandatory rep_num_cols
12211226
if (is.null(rep_cols)) {
12221227
rep_cols <- num_rep_cols(obj)
@@ -1230,7 +1235,7 @@ paginate_to_mpfs <- function(obj,
12301235

12311236
# Checking colwidths
12321237
if (is.null(colwidths)) {
1233-
colwidths <- mf_col_widths(mpf) %||% propose_column_widths(mpf, fontspec = fontspec)
1238+
colwidths <- mf_col_widths(mpf) %||% propose_column_widths(mpf, fontspec = fontspec, round_type = round_type)
12341239
} else {
12351240
cur_ncol <- ncol(mpf)
12361241
if (!.is_listing_mf(mpf)) {
@@ -1299,18 +1304,19 @@ paginate_to_mpfs <- function(obj,
12991304
fontspec = fontspec,
13001305
verbose = verbose,
13011306
rep_cols = rep_cols,
1302-
page_num = page_num
1307+
page_num = page_num,
1308+
round_type = round_type
13031309
)
13041310
return(deep_pag)
13051311
} else if (has_page_title(fpags[[1]])) {
13061312
obj <- fpags[[1]]
13071313
}
13081314

13091315
## we run into forced pagination, but life is short and this should work fine.
1310-
mpf <- matrix_form(obj, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec)
1316+
mpf <- matrix_form(obj, TRUE, TRUE, indent_size = indent_size, fontspec = fontspec, round_type = round_type)
13111317
num_rep_cols(mpf) <- rep_cols
13121318
if (is.null(colwidths)) {
1313-
colwidths <- mf_col_widths(mpf) %||% propose_column_widths(mpf, fontspec = fontspec)
1319+
colwidths <- mf_col_widths(mpf) %||% propose_column_widths(mpf, fontspec = fontspec, round_type = round_type)
13141320
}
13151321
mf_col_widths(mpf) <- colwidths
13161322
mf_colgap(mpf) <- col_gap
@@ -1336,7 +1342,8 @@ paginate_to_mpfs <- function(obj,
13361342
rep_cols = rep_cols,
13371343
verbose = verbose,
13381344
col_gap = col_gap,
1339-
fontspec = fontspec
1345+
fontspec = fontspec,
1346+
round_type = round_type
13401347
)
13411348

13421349
pagmats <- lapply(page_indices$pag_row_indices, function(ii) {
@@ -1460,7 +1467,9 @@ diagnose_pagination <- function(obj,
14601467
cpp = NA_integer_,
14611468
min_siblings = 2,
14621469
nosplitin = character(),
1463-
colwidths = propose_column_widths(matrix_form(obj, TRUE), fontspec = fontspec),
1470+
colwidths = propose_column_widths(matrix_form(obj, TRUE, round_type = round_type),
1471+
fontspec = fontspec, round_type = round_type
1472+
),
14641473
tf_wrap = FALSE,
14651474
max_width = NULL,
14661475
indent_size = 2,
@@ -1473,6 +1482,7 @@ diagnose_pagination <- function(obj,
14731482
font_size,
14741483
lineheight
14751484
),
1485+
round_type = c("iec", "sas"),
14761486
...) {
14771487
new_dev <- open_font_dev(fontspec)
14781488
if (new_dev) {
@@ -1496,7 +1506,8 @@ diagnose_pagination <- function(obj,
14961506
col_gap = col_gap,
14971507
min_siblings = min_siblings,
14981508
nosplitin = nosplitin,
1499-
fontspec = fontspec
1509+
fontspec = fontspec,
1510+
round_type = round_type
15001511
))
15011512
}
15021513

@@ -1520,6 +1531,7 @@ diagnose_pagination <- function(obj,
15201531
min_siblings = min_siblings,
15211532
nosplitin = nosplitin,
15221533
fontspec = fontspec,
1534+
round_type = round_type,
15231535
verbose = TRUE
15241536
)
15251537
)

R/tostring.R

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ do_cell_fnotes_wrap <- function(mat, widths, max_width, tf_wrap, fontspec, expan
398398
return(has_correct_indentation || !nzchar(mf_str[xx, 1])) # "" is still an ok indentation
399399
}
400400
# Cases where no indent are true by definition
401-
return(TRUE)
401+
TRUE
402402
}, logical(1))
403403

404404
if (any(!correct_indentation)) {
@@ -607,6 +607,7 @@ calc_str_adj <- function(str, fontspec) {
607607
#'
608608
#' @inheritParams MatrixPrintForm
609609
#' @inheritParams open_font_dev
610+
#' @inheritParams format_value
610611
#' @param widths (`numeric` or `NULL`)\cr Proposed widths for the columns of `x`. The expected
611612
#' length of this numeric vector can be retrieved with `ncol(x) + 1` as the column of row names
612613
#' must also be considered.
@@ -644,7 +645,8 @@ setMethod("toString", "MatrixPrintForm", function(x,
644645
col_gap = mf_colgap(x),
645646
hsep = NULL,
646647
fontspec = font_spec(),
647-
ttype_ok = FALSE) {
648+
ttype_ok = FALSE,
649+
round_type = c("iec", "sas")) {
648650
checkmate::assert_flag(tf_wrap)
649651

650652
## we are going to use the pdf device and grid to understand the actual
@@ -660,7 +662,7 @@ setMethod("toString", "MatrixPrintForm", function(x,
660662
"If you truly want this behavior please set ttype_ok = TRUE in the call to toString/export_as_txt/export_as_pdf"
661663
)
662664
}
663-
mat <- matrix_form(x, indent_rownames = TRUE, fontspec = fontspec)
665+
mat <- matrix_form(x, indent_rownames = TRUE, fontspec = fontspec, round_type = round_type)
664666

665667
# Check for \n in mat strings -> if there are any, matrix_form did not work
666668
if (any(grepl("\n", mf_strings(mat)))) {
@@ -694,7 +696,7 @@ setMethod("toString", "MatrixPrintForm", function(x,
694696
# if cells are decimal aligned, run propose column widths
695697
# if the provided widths is less than proposed width, return an error
696698
if (any_dec_align(mf_aligns(mat))) {
697-
aligned <- propose_column_widths(x, fontspec = fontspec)
699+
aligned <- propose_column_widths(x, fontspec = fontspec, round_type = round_type)
698700

699701
# catch any columns that require widths more than what is provided
700702
if (!is.null(widths)) {
@@ -716,7 +718,7 @@ setMethod("toString", "MatrixPrintForm", function(x,
716718
# Column widths are fixed here
717719
if (is.null(widths)) {
718720
# if mf does not have widths -> propose them
719-
widths <- mf_col_widths(x) %||% propose_column_widths(x, fontspec = fontspec)
721+
widths <- mf_col_widths(x) %||% propose_column_widths(x, fontspec = fontspec, round_type = round_type)
720722
} else {
721723
mf_col_widths(x) <- widths
722724
}
@@ -1362,6 +1364,7 @@ spans_to_viscell <- function(spans) {
13621364
#' Row names are also considered a column for the output.
13631365
#'
13641366
#' @inheritParams open_font_dev
1367+
#' @inheritParams format_value
13651368
#' @param x (`ANY`)\cr a `MatrixPrintForm` object, or an object with a `matrix_form` method.
13661369
#' @param indent_size (`numeric(1)`)\cr indent size, in characters. Ignored when `x` is already
13671370
#' a `MatrixPrintForm` object in favor of information there.
@@ -1375,14 +1378,15 @@ spans_to_viscell <- function(spans) {
13751378
#' @export
13761379
propose_column_widths <- function(x,
13771380
indent_size = 2,
1378-
fontspec = font_spec()) {
1381+
fontspec = font_spec(),
1382+
round_type = c("iec", "sas")) {
13791383
new_dev <- open_font_dev(fontspec)
13801384
if (new_dev) {
13811385
on.exit(close_font_dev())
13821386
}
13831387

13841388
if (!is(x, "MatrixPrintForm")) {
1385-
x <- matrix_form(x, indent_rownames = TRUE, indent_size = indent_size, fontspec = fontspec)
1389+
x <- matrix_form(x, indent_rownames = TRUE, indent_size = indent_size, fontspec = fontspec, round_type = round_type)
13861390
}
13871391
body <- mf_strings(x)
13881392
spans <- mf_spans(x)

0 commit comments

Comments
 (0)