From a2e1c9333c96bc77110fc0dca29927d328db8123 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Wed, 4 May 2022 21:25:15 +1000 Subject: [PATCH 01/18] Adding feature for when a single shadow is provided amongst two or more shadows on other columns in order to fix merge issue --- R/prj_project.R | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/R/prj_project.R b/R/prj_project.R index 6bb59bc..28768d7 100644 --- a/R/prj_project.R +++ b/R/prj_project.R @@ -82,7 +82,7 @@ prj_cast_shadow <- function(.data, .digits = NULL) { out <- glue_each_in(col_shadow(col_i), col_i) } - if (length(out) > 1) { + if (length(out) > 1 | (!is_col_row(col_i) & !is.null(names(out)))) { out <- do.call(vctrs::vec_cbind, out) } else if (length(out) == 1){ out <- data.frame(out[[1]], stringsAsFactors = FALSE) @@ -113,9 +113,11 @@ prj_cast_shadow <- function(.data, .digits = NULL) { names(col_spanners) <- NULL col_names <- paste(col_spanners, col_labels, sep = ".") - col_names[is.na(col_spanners)] <- col_labels[is.na(col_spanners)] + col_names[is.na(col_spanners) | col_spanners == col_labels] <- col_labels[is.na(col_spanners) | col_spanners == col_labels] names(col_names) <- NULL + + # Output out <- do.call(cbind, out) From 9ac1f06fc60d9b8b456b4d4845e49ffb9f64ca87 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Wed, 4 May 2022 21:48:34 +1000 Subject: [PATCH 02/18] Increment version number --- DESCRIPTION | 2 +- NEWS.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index efd2a72..5d4c0cc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: projectable Title: Metadata-Rich Tables -Version: 0.0.6 +Version: 0.0.6.9000 Authors@R: c(person(given = "Kinto", family = "Behr", diff --git a/NEWS.md b/NEWS.md index cb2c7e2..8800e03 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,5 @@ +# projectable (development version) + # projectable 0.0.6 * Deprecated `spec_col_freq()`. This function was implemented in a fairly unsafe way. It is being dropped without deprecation since it is purely a convenience function, the usefulness of which is limited anyway. From 3ca3573018d4e68801afe08c51e51fecf04afa7c Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Thu, 5 May 2022 15:12:22 +1000 Subject: [PATCH 03/18] Adding news --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 8800e03..ca6e858 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # projectable (development version) +* Enhancing `prj_cast_shadow()` to allow the user to specify a label in the shadow definition, e.g., `n = "{dec_dig3(100*p, 2)}"`, will make give the label a title of "n". If the shadow is unnamed, then, there won't be a spanner row in the formatted table. + # projectable 0.0.6 * Deprecated `spec_col_freq()`. This function was implemented in a fairly unsafe way. It is being dropped without deprecation since it is purely a convenience function, the usefulness of which is limited anyway. From 3629fc1c300741ef469702bb110a659a6bfeca36 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Thu, 5 May 2022 15:24:36 +1000 Subject: [PATCH 04/18] updates to docs --- man/projectable-package.Rd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/projectable-package.Rd b/man/projectable-package.Rd index 20224ed..ae427c1 100644 --- a/man/projectable-package.Rd +++ b/man/projectable-package.Rd @@ -6,7 +6,8 @@ \alias{projectable-package} \title{projectable: Metadata-Rich Tables} \description{ -Produce table-like objects made up of special metadata-rich column vectors, and project them into two dimensions. +Produce table-like objects made up of special metadata-rich + column vectors, and project them into two dimensions. } \seealso{ Useful links: From 611b8111f11e99a4057de4f984f4a296233e1a04 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 13:43:56 +1000 Subject: [PATCH 05/18] Changes: * Adding renaming of dupe column names as suggested in #29 * Adding examples to NEWS and function documentation * Adding tests --- NEWS.md | 23 +++++++++++++- R/prj_project.R | 50 +++++++++++++++++++++++++++++++ tests/testthat/test-prj_project.R | 49 ++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ca6e858..0e0b27e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,27 @@ # projectable (development version) -* Enhancing `prj_cast_shadow()` to allow the user to specify a label in the shadow definition, e.g., `n = "{dec_dig3(100*p, 2)}"`, will make give the label a title of "n". If the shadow is unnamed, then, there won't be a spanner row in the formatted table. +* Enhancing `prj_cast_shadow()` to allow the user to specify a label in the shadow definition, e.g., `n = "{dec_dig3(100*p, 2)}"`, will give the label a title of "n". If the shadow is unnamed, then, there won't be a spanner row in the formatted table. Where column names are duplicated, then a warning will be thrown and handled internally by incrementing the column names. + +``` + +tbl <- mtcars %>% + prj_tbl_rows( + Cylinders = cyl, + Transmission = list(Automatic = am %in% 0, Manual = am %in% 1), + ) %>% + prj_tbl_cols( + `V-Shaped` = col_freq(n = vs %in% 1, N = vs %in% 0:1), + `Not V-shaped` = col_freq(n = vs %in% 0, N = vs %in% 0:1) + ) %>% + prj_tbl_summarise() + +tbl %>% + prj_project(list( + `V-Shaped` = c(p = "{signif(p, 2)} ({n})"), + `Not V-shaped` = c(p = "{signif(p, 2)} ({n})") + )) + +``` # projectable 0.0.6 diff --git a/R/prj_project.R b/R/prj_project.R index 28768d7..c2b4ba9 100644 --- a/R/prj_project.R +++ b/R/prj_project.R @@ -49,6 +49,35 @@ #' `Not V-shaped` = "{signif(p, 2)} ({n})" #' )) #' +#' # With renamed columns +#' prj_project(my_tbl, list( +#' `V-Shaped` = c(`V-Shaped %` = "{signif(p, 2)} ({n})"), +#' `Not V-shaped` = c(`Not V-Shaped %` = "{signif(p, 2)} ({n})") +#' )) +#' +#' # With same renamed columns +#' ## Due to duplicate `%` as column names, these will be incremented +#' prj_project(my_tbl, list( +#' `V-Shaped` = c(`%` = "{signif(p, 2)} ({n})"), +#' `Not V-shaped` = c(`%` = "{signif(p, 2)} ({n})") +#' )) +#' +#' +#' # With multiple renamed columns +#' prj_project(my_tbl, list( +#' `V-Shaped` = c(`%` = "{signif(p, 2)} ({n})", `n` = "{n}"), +#' `Not V-shaped` = c(`%` = "{signif(p, 2)} ({n})", `n` = "{n}") +#' )) +#' +#' A mix of some multiple renamed columns, and not renamed columns +#' prj_project( +#' my_tbl, list( +#' `V-Shaped` = c("{signif(p, 2)} ({n})"), +#' `Not V-shaped` = c(p = "{signif(p, 2)} ({n})", n = "{n}") +#' ) +#' ) +#' +#' #' # Produce a `gt` display object #' out <- prj_gt(my_tbl, list( #' `V-Shaped` = "{signif(p, 2)} ({n})", @@ -61,6 +90,7 @@ #' `Not V-shaped` = "{signif(p, 2)} ({n})" #' )) #' +#' #' @name prj_project # Project table ---------------------------------------------------------------- prj_project <- function(.data, .cols = list(), .digits = getOption("prj_digits")) { @@ -106,6 +136,8 @@ prj_cast_shadow <- function(.data, .digits = NULL) { if(is.null(col_labels)) col_labels <- character(0) names(col_labels) <- NULL + + col_spanners <- unlist(lapply(names(out), function (x) { rep(x, ncol(out[[x]])) })) @@ -113,6 +145,7 @@ prj_cast_shadow <- function(.data, .digits = NULL) { names(col_spanners) <- NULL col_names <- paste(col_spanners, col_labels, sep = ".") + col_names[is.na(col_spanners) | col_spanners == col_labels] <- col_labels[is.na(col_spanners) | col_spanners == col_labels] names(col_names) <- NULL @@ -121,6 +154,23 @@ prj_cast_shadow <- function(.data, .digits = NULL) { # Output out <- do.call(cbind, out) + # Renaming duplicated column names + if (any(duplicated(names(out)))) { + warning("\nColumn name duplicated: `", names(out)[duplicated(names(out))], "`\nResolving by incrementing...") + + which_dups <- which(names(out) == names(out)[duplicated(names(out))]) + rename_dups <- paste0(names(out)[which(names(out) == names(out)[duplicated(names(out))])], + seq_len(length(which(names(out) == names(out)[duplicated(names(out))])))) + + + col_labels[which_dups] <- rename_dups + + mapply(function(elem, i) { + names(out)[elem] <<- rename_dups[i] + }, which_dups, seq_len(length(which_dups))) + + } + validate_projection( new_projection( tibble::as_tibble(out), diff --git a/tests/testthat/test-prj_project.R b/tests/testthat/test-prj_project.R index 7b6bf28..afb6681 100644 --- a/tests/testthat/test-prj_project.R +++ b/tests/testthat/test-prj_project.R @@ -153,3 +153,52 @@ testthat::test_that("prj_flex", { ) }) + +testthat::test_that("Handling duplicate column names", { + + + + dat <- prj_tbl_rows(mtcars, + Cylinders = cyl, + Transmission = list(Automatic = am %in% 0, Manual = am %in% 1), + ) + + dat <- prj_tbl_summarise( + prj_tbl_cols(dat, + `V-Shaped` = col_freq(n = vs %in% 1, N = vs %in% 0:1), + `Not V-shaped` = col_freq(n = vs %in% 0, N = vs %in% 0:1) + )) + + testthat::expect_warning( + + testthat::expect_true( + all( + names( + prj_project( + dat, list( + `V-Shaped` = c(p = "{signif(p, 2)} ({n})"), + `Not V-shaped` = c(p = "{signif(p, 2)} ({n})") + ) + ) + )[3:4] == c("p1", "p2") + ) + ) + + ) + + # A mix of multiple columns, and a single column + + all( + names( + prj_project( + dat, list( + `V-Shaped` = c("{signif(p, 2)} ({n})"), + `Not V-shaped` = c(p = "{signif(p, 2)} ({n})", n = "{n}") + ) + ) + )[3:5] == c("V-Shaped", "Not V-shaped.p", "Not V-shaped.n") + ) + + +}) + From beea9ab58098053922c38d6d874cc70b22e0547f Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:28:20 +1000 Subject: [PATCH 06/18] Starting to move functions from srcreporting into projectable --- DESCRIPTION | 2 +- NAMESPACE | 3 ++ NEWS.md | 4 ++ R/public.R | 102 ++++++++++++++++++++++++++++++++++++++++++ _pkgdown.yml | 5 +++ man/public_formats.Rd | 51 +++++++++++++++++++++ man/rounding.Rd | 28 ++++++++++++ 7 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 R/public.R create mode 100644 man/public_formats.Rd create mode 100644 man/rounding.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 5d4c0cc..c41a357 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: projectable Title: Metadata-Rich Tables -Version: 0.0.6.9000 +Version: 0.0.6.9001 Authors@R: c(person(given = "Kinto", family = "Behr", diff --git a/NAMESPACE b/NAMESPACE index 5fc1e30..9654fa5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -44,6 +44,7 @@ export(col_binomial) export(col_freq) export(col_row) export(col_shadow) +export(dec_dig3) export(face_value) export(is_col) export(is_col_binomial) @@ -58,4 +59,6 @@ export(prj_shadow) export(prj_tbl_cols) export(prj_tbl_rows) export(prj_tbl_summarise) +export(public_ci) +export(public_num) import(vctrs) diff --git a/NEWS.md b/NEWS.md index 0e0b27e..a94173e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,6 +23,10 @@ tbl %>% ``` + +* Moving public functions `dec_dig3()`, `public_num()` and `public_ci()` from srcreporting into projectable + + # projectable 0.0.6 * Deprecated `spec_col_freq()`. This function was implemented in a fairly unsafe way. It is being dropped without deprecation since it is purely a convenience function, the usefulness of which is limited anyway. diff --git a/R/public.R b/R/public.R new file mode 100644 index 0000000..cb0a0b0 --- /dev/null +++ b/R/public.R @@ -0,0 +1,102 @@ +#' Format numbers for public consumption +#' +#' In public reports, cells are only reported if the N count is greater than +#' some minimum number (usually 25). In addition, we: +#' * Round figures to some number of digits, retaining trailing 0s, +#' e.g. 25 -> 25.0 +#' * Display confidence intervals in brackets beside estimates, +#' e.g. '25.0 (24.5, 25.5)' +#' +#' @param x A numeric vector, typically the 'face value' of a projectable `col` +#' @param ci_lower A numeric vector, the lower bound of the confidence interval +#' @param ci_upper A numeric vector, the upper bound of the confidence interval +#' @param N A numeric vector, the base count +#' @param digits A number, the number of digits to values to +#' @param min_N A number, the minimum N required for values to be reportable +#' +#' @return A character vector +#' +#' @examples +#' +#' # Present a formatted number with suppressions applied: +#' x <- projectable::col_freq(1:5, 1:5*10, summarised = TRUE) +#' x <- projectable::prj_project_col(x) +#' public_num(x$p, x$N, digits = 2) +#' +#' # Present a formatted number and its confidence interval with suppressions applied +#' x <- projectable::col_binomial(1:5, 1:5*10, summarised = TRUE) +#' x <- projectable::prj_project_col(x) +#' public_ci(x$p, x$N, x$ci_lower, x$ci_upper) +#' +#' @name public_formats +NULL + +#' @export +#' @rdname public_formats +public_num <- function(x, N, digits = 1, min_N = 25) { + N <- match_lengths(N, x) + + dplyr::case_when( + is.na(x) | is.na(N) | N %in% 0 ~ "", # No records in cell + N < min_N ~ "n/a", # Too few records in cell + TRUE ~ dec_dig3(x, digits) + ) +} + + + +#' @export +#' @rdname public_formats +public_ci <- function(x, N, ci_lower = NA, ci_upper = NA, digits = 1, min_N = 25) { + N <- match_lengths(N, x) + miss <- is.na(x) & is.na(ci_lower) & is.na(ci_upper) + + x <- as.character(dec_dig3(x, digits, "n/a")) + if (any(!is.na(ci_lower) | !is.na(ci_upper))) { + ci_lower <- dec_dig3(ci_lower, digits, "n/a") + ci_upper <- dec_dig3(ci_upper, digits, "n/a") + x <- paste0(x, " (", ci_lower, ", ", ci_upper, ")") + } + + dplyr::case_when( + is.na(x) | is.na(N) | N %in% 0 ~ "", # No records in cell + N < min_N ~ "n/a", # Too few records in cell + miss ~ "", # All figures missing + TRUE ~ x + ) +} + +#' Rounding +#' +#' `dec_dig3()` is essentially a wrapper for `srcutils::round2()`. It formats +#' numbers by: +#' * Rounding them using `srcutils::round2()` +#' * Inserting commas as thousands separators (e.g. as in "10,000") +#' * Retaining trailing 0s (e.g. as in "10.0") +#' +#' @param x A numeric vector +#' @param n An integer, how many digits to round to +#' @param na_replacement A string, what to replace NAs with +#' +#' @return A character vector +#' @name rounding +NULL + +#' @name rounding +#' @export +dec_dig3 <- function(x, n, na_replacement = '') { + x <- round2(as.numeric(x), n) + if (n < 0) n <- 0 + x <- ifelse(is.na(x), na_replacement, formatC(x, format = "f", digits = n, big.mark = ",")) + x +} + +round2 <- function (x, n) { + x <- round(x, 10) + posneg <- sign(x) + z <- abs(x) * 10^n + z <- z + 0.5 + z <- trunc(z) + z <- z/10^n + z * posneg +} diff --git a/_pkgdown.yml b/_pkgdown.yml index c2bc40a..52c0f47 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -17,3 +17,8 @@ reference: contents: - '`prj_project`' - '`prj_shadow`' += title: Public presentations + contents: + - 'public_num' + - 'public_ci' + - 'dec_dig3' diff --git a/man/public_formats.Rd b/man/public_formats.Rd new file mode 100644 index 0000000..4274be0 --- /dev/null +++ b/man/public_formats.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/public.R +\name{public_formats} +\alias{public_formats} +\alias{public_num} +\alias{public_ci} +\title{Format numbers for public consumption} +\usage{ +public_num(x, N, digits = 1, min_N = 25) + +public_ci(x, N, ci_lower = NA, ci_upper = NA, digits = 1, min_N = 25) +} +\arguments{ +\item{x}{A numeric vector, typically the 'face value' of a projectable \code{col}} + +\item{N}{A numeric vector, the base count} + +\item{digits}{A number, the number of digits to values to} + +\item{min_N}{A number, the minimum N required for values to be reportable} + +\item{ci_lower}{A numeric vector, the lower bound of the confidence interval} + +\item{ci_upper}{A numeric vector, the upper bound of the confidence interval} +} +\value{ +A character vector +} +\description{ +In public reports, cells are only reported if the N count is greater than +some minimum number (usually 25). In addition, we: +\itemize{ +\item Round figures to some number of digits, retaining trailing 0s, +e.g. 25 -> 25.0 +\item Display confidence intervals in brackets beside estimates, +e.g. '25.0 (24.5, 25.5)' +} +} +\examples{ + +# Present a formatted number with suppressions applied: +x <- projectable::col_freq(1:5, 1:5*10, summarised = TRUE) +x <- projectable::prj_project_col(x) +public_num(x$p, x$N, digits = 2) + +# Present a formatted number and its confidence interval with suppressions applied +x <- projectable::col_binomial(1:5, 1:5*10, summarised = TRUE) +x <- projectable::prj_project_col(x) +public_ci(x$p, x$N, x$ci_lower, x$ci_upper) + +} diff --git a/man/rounding.Rd b/man/rounding.Rd new file mode 100644 index 0000000..8b5193a --- /dev/null +++ b/man/rounding.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/public.R +\name{rounding} +\alias{rounding} +\alias{dec_dig3} +\title{Rounding} +\usage{ +dec_dig3(x, n, na_replacement = "") +} +\arguments{ +\item{x}{A numeric vector} + +\item{n}{An integer, how many digits to round to} + +\item{na_replacement}{A string, what to replace NAs with} +} +\value{ +A character vector +} +\description{ +\code{dec_dig3()} is essentially a wrapper for \code{srcutils::round2()}. It formats +numbers by: +\itemize{ +\item Rounding them using \code{srcutils::round2()} +\item Inserting commas as thousands separators (e.g. as in "10,000") +\item Retaining trailing 0s (e.g. as in "10.0") +} +} From 7e2fd689bf92e0d8a7d82fac458d91a918bfda3b Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:28:47 +1000 Subject: [PATCH 07/18] Adding tests for dupe column names, and preserving formatting --- tests/testthat/test-prj_project.R | 125 +++++++++++++++++++----------- 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/tests/testthat/test-prj_project.R b/tests/testthat/test-prj_project.R index afb6681..3c4590e 100644 --- a/tests/testthat/test-prj_project.R +++ b/tests/testthat/test-prj_project.R @@ -67,6 +67,85 @@ testthat::test_that("prj_project metadata", { ) }) + +testthat::test_that("prj_project handling duplicate column names", { + + + + dat <- prj_tbl_rows(mtcars, + Cylinders = cyl, + Transmission = list(Automatic = am %in% 0, Manual = am %in% 1), + ) + + dat <- prj_tbl_summarise( + prj_tbl_cols(dat, + `V-Shaped` = col_freq(n = vs %in% 1, N = vs %in% 0:1), + `Not V-shaped` = col_freq(n = vs %in% 0, N = vs %in% 0:1) + )) + + testthat::expect_warning( + + testthat::expect_true( + all( + names( + prj_project( + dat, list( + `V-Shaped` = c(p = "{signif(p, 2)} ({n})"), + `Not V-shaped` = c(p = "{signif(p, 2)} ({n})") + ) + ) + )[3:4] == c("p1", "p2") + ) + ) + + ) + + # A mix of multiple columns, and a single column + + all( + names( + prj_project( + dat, list( + `V-Shaped` = c("{signif(p, 2)} ({n})"), + `Not V-shaped` = c(p = "{signif(p, 2)} ({n})", n = "{n}") + ) + ) + )[3:5] == c("V-Shaped", "Not V-shaped.p", "Not V-shaped.n") + ) + + +}) + + +test_that("prj_project formatting retained", { + + options("prj_digits" = NULL) + + dat <- prj_tbl_rows(mtcars, + Cylinders = cyl, + Transmission = list(Automatic = am %in% 0, Manual = am %in% 1), + ) + + dat <- prj_tbl_summarise( + prj_tbl_cols(dat, + `V-Shaped` = col_freq(n = vs %in% 1, N = vs %in% 0:1), + `Not V-shaped` = col_freq(n = vs %in% 0, N = vs %in% 0:1) + )) + + + dat <- prj_project( + dat, list( + `V-Shaped` = c(p = "{dec_dig3(p, 2)}") + ) + ) + + expect_equal(dat[dat$row_spanner == "Cylinders" & dat$rows == 8, 3][[1]], "0.00") + + + +}) + + # proje_gt ---------------------------------------------------------------- y <- prj_tbl_rows(mtcars, cyl) y <- prj_tbl_cols(y, v = col_freq(vs %in% 1, vs %in% 0:1)) @@ -154,51 +233,5 @@ testthat::test_that("prj_flex", { }) -testthat::test_that("Handling duplicate column names", { - - - dat <- prj_tbl_rows(mtcars, - Cylinders = cyl, - Transmission = list(Automatic = am %in% 0, Manual = am %in% 1), - ) - - dat <- prj_tbl_summarise( - prj_tbl_cols(dat, - `V-Shaped` = col_freq(n = vs %in% 1, N = vs %in% 0:1), - `Not V-shaped` = col_freq(n = vs %in% 0, N = vs %in% 0:1) - )) - - testthat::expect_warning( - - testthat::expect_true( - all( - names( - prj_project( - dat, list( - `V-Shaped` = c(p = "{signif(p, 2)} ({n})"), - `Not V-shaped` = c(p = "{signif(p, 2)} ({n})") - ) - ) - )[3:4] == c("p1", "p2") - ) - ) - - ) - - # A mix of multiple columns, and a single column - - all( - names( - prj_project( - dat, list( - `V-Shaped` = c("{signif(p, 2)} ({n})"), - `Not V-shaped` = c(p = "{signif(p, 2)} ({n})", n = "{n}") - ) - ) - )[3:5] == c("V-Shaped", "Not V-shaped.p", "Not V-shaped.n") - ) - - -}) From d587d20b55430a43a2c20491809519fca19de82a Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:29:01 +1000 Subject: [PATCH 08/18] Adding to examples for dupe column names --- man/prj_project.Rd | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/man/prj_project.Rd b/man/prj_project.Rd index 0f13248..fba9ed3 100644 --- a/man/prj_project.Rd +++ b/man/prj_project.Rd @@ -76,6 +76,35 @@ prj_project(my_tbl, list( `Not V-shaped` = "{signif(p, 2)} ({n})" )) +# With renamed columns +prj_project(my_tbl, list( + `V-Shaped` = c(`V-Shaped \%` = "{signif(p, 2)} ({n})"), + `Not V-shaped` = c(`Not V-Shaped \%` = "{signif(p, 2)} ({n})") +)) + +# With same renamed columns +## Due to duplicate `\%` as column names, these will be incremented +prj_project(my_tbl, list( + `V-Shaped` = c(`\%` = "{signif(p, 2)} ({n})"), + `Not V-shaped` = c(`\%` = "{signif(p, 2)} ({n})") +)) + + +# With multiple renamed columns +prj_project(my_tbl, list( + `V-Shaped` = c(`\%` = "{signif(p, 2)} ({n})", `n` = "{n}"), + `Not V-shaped` = c(`\%` = "{signif(p, 2)} ({n})", `n` = "{n}") +)) + +A mix of some multiple renamed columns, and not renamed columns +prj_project( + my_tbl, list( + `V-Shaped` = c("{signif(p, 2)} ({n})"), + `Not V-shaped` = c(p = "{signif(p, 2)} ({n})", n = "{n}") + ) +) + + # Produce a `gt` display object out <- prj_gt(my_tbl, list( `V-Shaped` = "{signif(p, 2)} ({n})", @@ -88,4 +117,5 @@ out <- prj_flex(my_tbl, list( `Not V-shaped` = "{signif(p, 2)} ({n})" )) + } From 653beca381903000a0744ae6ed2ee402da74e857 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:34:25 +1000 Subject: [PATCH 09/18] Resolving test error --- R/prj_project.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/prj_project.R b/R/prj_project.R index c2b4ba9..f4d9521 100644 --- a/R/prj_project.R +++ b/R/prj_project.R @@ -69,7 +69,7 @@ #' `Not V-shaped` = c(`%` = "{signif(p, 2)} ({n})", `n` = "{n}") #' )) #' -#' A mix of some multiple renamed columns, and not renamed columns +#' # A mix of some multiple renamed columns, and not renamed columns #' prj_project( #' my_tbl, list( #' `V-Shaped` = c("{signif(p, 2)} ({n})"), From 3a78bbd94531f6ed2b8b59ce8eb15cb4338629a0 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:44:47 +1000 Subject: [PATCH 10/18] Adding util from screporting, needed for the public functions --- R/utils.R | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 R/utils.R diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 0000000..a5efdc2 --- /dev/null +++ b/R/utils.R @@ -0,0 +1,33 @@ + + +#' Make sure the lengths of two vectors are the same. +#' +#' Recycle `x` to match length of `to`; throw an error if this is not possible. +#' +#' Copied from `srcsample`. +#' +#' @param x A vector +#' @param to Another vector +#' @param stop_on_fail A logical determining whether or not an error is thrown +#' +#' @return `x` recycled to have a length matching that of `to` +#' @keywords internal +#' @noRd +match_lengths <- function(x, to, stop_on_fail = TRUE) { + stopifnot(is.atomic(x)) + stopifnot(is.atomic(to)) + if (length(x) == length(to)) return(x) + x_name <- deparse(substitute(x)) + to_name <- deparse(substitute(to)) + + if (length(x) == 1) { + x <- rep(x, length(to)) + } else if (stop_on_fail) { + stop(paste0( + "Cannot recycle `", x_name, "` (length ", length(x), ") ", + "to match `", to_name, "` (length ", length(to), ")" + ), call. = FALSE) + } + + x +} From 6725baa9208c8331c42a5e57d3f01a0aa3455f80 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:45:03 +1000 Subject: [PATCH 11/18] Adding dplyr as an import --- DESCRIPTION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index c41a357..5e8d73a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -22,13 +22,13 @@ Imports: glue, stats, rlang, - tidyselect + tidyselect, + dplyr Suggests: testthat, gt, knitr, rmarkdown, - dplyr, flextable Encoding: UTF-8 LazyData: true From 3cfc990cda4b2897954caa8f2576a83fcfca0aac Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:45:11 +1000 Subject: [PATCH 12/18] Debugging --- man/prj_project.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/prj_project.Rd b/man/prj_project.Rd index fba9ed3..6ce320b 100644 --- a/man/prj_project.Rd +++ b/man/prj_project.Rd @@ -96,7 +96,7 @@ prj_project(my_tbl, list( `Not V-shaped` = c(`\%` = "{signif(p, 2)} ({n})", `n` = "{n}") )) -A mix of some multiple renamed columns, and not renamed columns +# A mix of some multiple renamed columns, and not renamed columns prj_project( my_tbl, list( `V-Shaped` = c("{signif(p, 2)} ({n})"), From ea8023538ea9464fa20877b5b873b8e888c618f9 Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 14:51:33 +1000 Subject: [PATCH 13/18] Adding myself to authors :) --- DESCRIPTION | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5e8d73a..5265e93 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,13 +1,11 @@ Package: projectable Title: Metadata-Rich Tables Version: 0.0.6.9001 -Authors@R: - c(person(given = "Kinto", - family = "Behr", - role = c("aut", "cre"), - email = "kinto.behr@srcentre.com.au"), - person(given = "The Social Research Centre", - role = "cph")) +Authors@R: c( + person(given = "Kinto", family = "Behr", role = c("aut", "cre"), email = "kinto.behr@srcentre.com.au"), + person("Paddy", "Tobias", , "paddy.tobias@srcentre.com.au", role = "aut"), + person(given = "The Social Research Centre", role = "cph") + ) Description: Produce table-like objects made up of special metadata-rich column vectors, and project them into two dimensions. License: GPL-3 From 02e245216ac8f676682cc15af1964e33b824237d Mon Sep 17 00:00:00 2001 From: Paddy Tobias Date: Fri, 27 May 2022 15:03:48 +1000 Subject: [PATCH 14/18] Updating docs --- man/projectable-package.Rd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/man/projectable-package.Rd b/man/projectable-package.Rd index ae427c1..c54ce58 100644 --- a/man/projectable-package.Rd +++ b/man/projectable-package.Rd @@ -21,6 +21,11 @@ Useful links: \author{ \strong{Maintainer}: Kinto Behr \email{kinto.behr@srcentre.com.au} +Authors: +\itemize{ + \item Paddy Tobias \email{paddy.tobias@srcentre.com.au} +} + Other contributors: \itemize{ \item The Social Research Centre [copyright holder] From 547be1c625852237b28689d4d9ee634fd2a3ea6c Mon Sep 17 00:00:00 2001 From: Anna Syme Date: Mon, 19 Feb 2024 15:49:40 +1100 Subject: [PATCH 15/18] removing public presenting functions from projectable to be in srcreporting #29 --- NEWS.md | 4 -- R/public.R | 102 --------------------------------------------------- _pkgdown.yml | 5 --- 3 files changed, 111 deletions(-) delete mode 100644 R/public.R diff --git a/NEWS.md b/NEWS.md index a94173e..0e0b27e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,10 +23,6 @@ tbl %>% ``` - -* Moving public functions `dec_dig3()`, `public_num()` and `public_ci()` from srcreporting into projectable - - # projectable 0.0.6 * Deprecated `spec_col_freq()`. This function was implemented in a fairly unsafe way. It is being dropped without deprecation since it is purely a convenience function, the usefulness of which is limited anyway. diff --git a/R/public.R b/R/public.R deleted file mode 100644 index cb0a0b0..0000000 --- a/R/public.R +++ /dev/null @@ -1,102 +0,0 @@ -#' Format numbers for public consumption -#' -#' In public reports, cells are only reported if the N count is greater than -#' some minimum number (usually 25). In addition, we: -#' * Round figures to some number of digits, retaining trailing 0s, -#' e.g. 25 -> 25.0 -#' * Display confidence intervals in brackets beside estimates, -#' e.g. '25.0 (24.5, 25.5)' -#' -#' @param x A numeric vector, typically the 'face value' of a projectable `col` -#' @param ci_lower A numeric vector, the lower bound of the confidence interval -#' @param ci_upper A numeric vector, the upper bound of the confidence interval -#' @param N A numeric vector, the base count -#' @param digits A number, the number of digits to values to -#' @param min_N A number, the minimum N required for values to be reportable -#' -#' @return A character vector -#' -#' @examples -#' -#' # Present a formatted number with suppressions applied: -#' x <- projectable::col_freq(1:5, 1:5*10, summarised = TRUE) -#' x <- projectable::prj_project_col(x) -#' public_num(x$p, x$N, digits = 2) -#' -#' # Present a formatted number and its confidence interval with suppressions applied -#' x <- projectable::col_binomial(1:5, 1:5*10, summarised = TRUE) -#' x <- projectable::prj_project_col(x) -#' public_ci(x$p, x$N, x$ci_lower, x$ci_upper) -#' -#' @name public_formats -NULL - -#' @export -#' @rdname public_formats -public_num <- function(x, N, digits = 1, min_N = 25) { - N <- match_lengths(N, x) - - dplyr::case_when( - is.na(x) | is.na(N) | N %in% 0 ~ "", # No records in cell - N < min_N ~ "n/a", # Too few records in cell - TRUE ~ dec_dig3(x, digits) - ) -} - - - -#' @export -#' @rdname public_formats -public_ci <- function(x, N, ci_lower = NA, ci_upper = NA, digits = 1, min_N = 25) { - N <- match_lengths(N, x) - miss <- is.na(x) & is.na(ci_lower) & is.na(ci_upper) - - x <- as.character(dec_dig3(x, digits, "n/a")) - if (any(!is.na(ci_lower) | !is.na(ci_upper))) { - ci_lower <- dec_dig3(ci_lower, digits, "n/a") - ci_upper <- dec_dig3(ci_upper, digits, "n/a") - x <- paste0(x, " (", ci_lower, ", ", ci_upper, ")") - } - - dplyr::case_when( - is.na(x) | is.na(N) | N %in% 0 ~ "", # No records in cell - N < min_N ~ "n/a", # Too few records in cell - miss ~ "", # All figures missing - TRUE ~ x - ) -} - -#' Rounding -#' -#' `dec_dig3()` is essentially a wrapper for `srcutils::round2()`. It formats -#' numbers by: -#' * Rounding them using `srcutils::round2()` -#' * Inserting commas as thousands separators (e.g. as in "10,000") -#' * Retaining trailing 0s (e.g. as in "10.0") -#' -#' @param x A numeric vector -#' @param n An integer, how many digits to round to -#' @param na_replacement A string, what to replace NAs with -#' -#' @return A character vector -#' @name rounding -NULL - -#' @name rounding -#' @export -dec_dig3 <- function(x, n, na_replacement = '') { - x <- round2(as.numeric(x), n) - if (n < 0) n <- 0 - x <- ifelse(is.na(x), na_replacement, formatC(x, format = "f", digits = n, big.mark = ",")) - x -} - -round2 <- function (x, n) { - x <- round(x, 10) - posneg <- sign(x) - z <- abs(x) * 10^n - z <- z + 0.5 - z <- trunc(z) - z <- z/10^n - z * posneg -} diff --git a/_pkgdown.yml b/_pkgdown.yml index 52c0f47..c2bc40a 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -17,8 +17,3 @@ reference: contents: - '`prj_project`' - '`prj_shadow`' -= title: Public presentations - contents: - - 'public_num' - - 'public_ci' - - 'dec_dig3' From de30cf269767bc687095692d2b834b6cc4687571 Mon Sep 17 00:00:00 2001 From: Anna Syme Date: Mon, 19 Feb 2024 15:50:17 +1100 Subject: [PATCH 16/18] remove dependancy on dplyr - only reference was in public.R which was moved to srcreporting anyway #29 --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5265e93..c4639dd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,7 +21,7 @@ Imports: stats, rlang, tidyselect, - dplyr + srcutils Suggests: testthat, gt, From 2ecfe07b7b538f586642cb3e320312f72e9f16cb Mon Sep 17 00:00:00 2001 From: Anna Syme Date: Mon, 19 Feb 2024 15:50:25 +1100 Subject: [PATCH 17/18] formatting clean up --- R/prj_project.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/prj_project.R b/R/prj_project.R index f4d9521..ac40528 100644 --- a/R/prj_project.R +++ b/R/prj_project.R @@ -156,7 +156,8 @@ prj_cast_shadow <- function(.data, .digits = NULL) { # Renaming duplicated column names if (any(duplicated(names(out)))) { - warning("\nColumn name duplicated: `", names(out)[duplicated(names(out))], "`\nResolving by incrementing...") + warning("\nColumn name duplicated: `", names(out)[duplicated(names(out))], + "`\nResolving by incrementing...", call. = FALSE) which_dups <- which(names(out) == names(out)[duplicated(names(out))]) rename_dups <- paste0(names(out)[which(names(out) == names(out)[duplicated(names(out))])], From f079435f1746aafc4b5db1976ce6b12482b1e41b Mon Sep 17 00:00:00 2001 From: Anna Syme Date: Mon, 19 Feb 2024 16:36:48 +1100 Subject: [PATCH 18/18] update versioning and build changes --- DESCRIPTION | 4 +-- NAMESPACE | 3 --- man/projectable-package.Rd | 3 +-- man/public_formats.Rd | 51 -------------------------------------- man/rounding.Rd | 28 --------------------- 5 files changed, 3 insertions(+), 86 deletions(-) delete mode 100644 man/public_formats.Rd delete mode 100644 man/rounding.Rd diff --git a/DESCRIPTION b/DESCRIPTION index c4639dd..da17b84 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: projectable Title: Metadata-Rich Tables -Version: 0.0.6.9001 +Version: 0.0.7 Authors@R: c( person(given = "Kinto", family = "Behr", role = c("aut", "cre"), email = "kinto.behr@srcentre.com.au"), person("Paddy", "Tobias", , "paddy.tobias@srcentre.com.au", role = "aut"), @@ -31,5 +31,5 @@ Suggests: Encoding: UTF-8 LazyData: true Roxygen: list(markdown = TRUE) -RoxygenNote: 7.1.2 +RoxygenNote: 7.2.3 VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 9654fa5..5fc1e30 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -44,7 +44,6 @@ export(col_binomial) export(col_freq) export(col_row) export(col_shadow) -export(dec_dig3) export(face_value) export(is_col) export(is_col_binomial) @@ -59,6 +58,4 @@ export(prj_shadow) export(prj_tbl_cols) export(prj_tbl_rows) export(prj_tbl_summarise) -export(public_ci) -export(public_num) import(vctrs) diff --git a/man/projectable-package.Rd b/man/projectable-package.Rd index c54ce58..1294f0d 100644 --- a/man/projectable-package.Rd +++ b/man/projectable-package.Rd @@ -6,8 +6,7 @@ \alias{projectable-package} \title{projectable: Metadata-Rich Tables} \description{ -Produce table-like objects made up of special metadata-rich - column vectors, and project them into two dimensions. +Produce table-like objects made up of special metadata-rich column vectors, and project them into two dimensions. } \seealso{ Useful links: diff --git a/man/public_formats.Rd b/man/public_formats.Rd deleted file mode 100644 index 4274be0..0000000 --- a/man/public_formats.Rd +++ /dev/null @@ -1,51 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/public.R -\name{public_formats} -\alias{public_formats} -\alias{public_num} -\alias{public_ci} -\title{Format numbers for public consumption} -\usage{ -public_num(x, N, digits = 1, min_N = 25) - -public_ci(x, N, ci_lower = NA, ci_upper = NA, digits = 1, min_N = 25) -} -\arguments{ -\item{x}{A numeric vector, typically the 'face value' of a projectable \code{col}} - -\item{N}{A numeric vector, the base count} - -\item{digits}{A number, the number of digits to values to} - -\item{min_N}{A number, the minimum N required for values to be reportable} - -\item{ci_lower}{A numeric vector, the lower bound of the confidence interval} - -\item{ci_upper}{A numeric vector, the upper bound of the confidence interval} -} -\value{ -A character vector -} -\description{ -In public reports, cells are only reported if the N count is greater than -some minimum number (usually 25). In addition, we: -\itemize{ -\item Round figures to some number of digits, retaining trailing 0s, -e.g. 25 -> 25.0 -\item Display confidence intervals in brackets beside estimates, -e.g. '25.0 (24.5, 25.5)' -} -} -\examples{ - -# Present a formatted number with suppressions applied: -x <- projectable::col_freq(1:5, 1:5*10, summarised = TRUE) -x <- projectable::prj_project_col(x) -public_num(x$p, x$N, digits = 2) - -# Present a formatted number and its confidence interval with suppressions applied -x <- projectable::col_binomial(1:5, 1:5*10, summarised = TRUE) -x <- projectable::prj_project_col(x) -public_ci(x$p, x$N, x$ci_lower, x$ci_upper) - -} diff --git a/man/rounding.Rd b/man/rounding.Rd deleted file mode 100644 index 8b5193a..0000000 --- a/man/rounding.Rd +++ /dev/null @@ -1,28 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/public.R -\name{rounding} -\alias{rounding} -\alias{dec_dig3} -\title{Rounding} -\usage{ -dec_dig3(x, n, na_replacement = "") -} -\arguments{ -\item{x}{A numeric vector} - -\item{n}{An integer, how many digits to round to} - -\item{na_replacement}{A string, what to replace NAs with} -} -\value{ -A character vector -} -\description{ -\code{dec_dig3()} is essentially a wrapper for \code{srcutils::round2()}. It formats -numbers by: -\itemize{ -\item Rounding them using \code{srcutils::round2()} -\item Inserting commas as thousands separators (e.g. as in "10,000") -\item Retaining trailing 0s (e.g. as in "10.0") -} -}