ddsjoberg/gtsummary

Feature request: Custom threshold for digits

csthiago opened this issue · 7 comments

Hi Daniel,

I was working in a way to use a custom threshold to define the number of digits in the tbl_summary. In your default "style_percent" function, it uses the cut-off of 10. Is it possible to make an additional argument for it?
Something like:

style_percent <- function(x,
                          digits = 0,
                          big.mark = ifelse(decimal.mark == ",", " ", ","),
                          decimal.mark = getOption("OutDec"),
                          prefix = "",
                          suffix = "",
                          symbol,
                          cutoff = 10
                          ...) {
  set_cli_abort_call()

  # deprecated arguments -------------------------------------------------------
  if (!missing(symbol)) {
    lifecycle::deprecate_soft(
      when = "2.0.3",
      what = "gtsummary::style_percent(symbol)",
      with = I("style_percent(suffix='%')")
    )
    if (isTRUE(symbol)) suffix = "%" # styler: off
  }

  # setting defaults -----------------------------------------------------------
  if (missing(decimal.mark)) {
    decimal.mark <-
      get_theme_element("style_number-arg:decimal.mark", default = decimal.mark)
  }
  if (missing(big.mark)) {
    big.mark <-
      get_theme_element("style_number-arg:big.mark", default = ifelse(decimal.mark == ",", "\U2009", ","))
  }

  y <- dplyr::case_when(
    x * 100 > cutoff ~ style_number(x * 100, digits = digits, big.mark = big.mark, decimal.mark = decimal.mark, prefix = prefix, suffix = suffix, ...),
    x == 0 ~ paste0(prefix, "0", suffix),
    x * 100 <= cutoff^(-(digits + 1)) ~ style_number(x * 100, digits = digits + 1, big.mark = big.mark, decimal.mark = decimal.mark, prefix = prefix, suffix = suffix, ...)

  )

  attributes(y) <- attributes(unclass(x))
  return(y)
}

Thanks

Dear @csthiago , Can you share what you want the result to look like? Perhaps there is a way to do so with the existing functions?

Also, there may be a function in the {scales} package that does precisely what you're looking for? Have you looked there?

For example,

the code

library(gtsummary)
trial |>
  tbl_summary(by = trt)

generate this table
image

I would want something like

library(gtsummary)
trial |>
  tbl_summary(by = trt,
digits = list(all_categorical()~ style_percent(cutoff=25))

and it would generate a table like:
image

So instead changing to +1 digits in number lower than 10, it would change by the specified cutoff

Ahh, I see now, thank you for the detailed response. We focus on tables that you see in publications in the package, but I can't say I've seen any journals, for example, request 2 sigfigs for percentages > 30%, 3 sigfigs for percentages between 10 and 30, and 2 sigfigs for percentages less than 10% 🤔

A bit of background, is that this function existed before style_sigfig() and that function essentially generalizes what we've done in the percent function and that is what we're going for here.

Indeed. I also can't remember to see something like that in papers. But one reviewer asked me to remove decimal places, and in very low numbers it wouldn't make sense. So I m trying to do 0 decimals for >1 and 1 decimal for ≤1.

Ah, I see. If I were in your shoes AND the journal doesn't have specific instructions on the rounding of percentages, I would tell them thanks for the comment and we prefer to keep the reporting consistent at 2 significant figures.

Otherwise, I would define a new simple function to get what you want like this and use it in tbl_summary():

library(gtsummary)

annoying_reviewer_comment_function <- function(x) {
  ifelse(
    x < 0.01,
    style_number(x, digits = 1, scale = 100),
    style_number(x, digits = 0, scale = 100)
  ) %>%
    paste0("%")
}

annoying_reviewer_comment_function(c(0.001, 0.02, 0.5))
#> [1] "0.1%" "2%"   "50%"

Created on 2024-10-03 with reprex v2.1.1

Thanks!
Just to confirm, I would use it like:

trial |>
  tbl_summary(by = trt,
digits = all_categorical()~annoying_reviewer_comment_function)

Like this:

library(gtsummary)

annoying_reviewer_comment_function <- function(x) {
  ifelse(
    x < 0.01,
    style_number(x, digits = 1, scale = 100),
    style_number(x, digits = 0, scale = 100)
  )
}

annoying_reviewer_comment_function(c(0.001, 0.02, 0.5))
#> [1] "0.1" "2"   "50"

tbl_summary(
  trial, 
  include = grade, 
  digits = all_categorical() ~ list(0, annoying_reviewer_comment_function)
) |> 
  as_kable()
Characteristic N = 200
Grade
I 68 (34%)
II 68 (34%)
III 64 (32%)

Created on 2024-10-03 with reprex v2.1.1