benjaminrich / table1

79 stars 26 forks source link

Customize render.missing for two decimal points for the percentages #107

Closed samuelsaari closed 1 year ago

samuelsaari commented 1 year ago

Related to issue #37, how can one customize the decimal places for the missing values? The default seems to be one, but would need 2 decimal places.

library(table1)
library(reprex)

# create data
f <- function(x, n, ...) factor(sample(x, n, replace=T, ...), levels=x)
set.seed(427)
n <- 146
dat <- data.frame(id=1:n)
dat$treat <- f(c("Placebo", "Treated"), n, prob=c(1, 2)) # 2:1 randomization
dat$age   <- sample(18:65, n, replace=TRUE)
dat$sex   <- f(c("Female", "Male"), n, prob=c(.6, .4))  # 60% female
dat$wt    <- round(exp(rnorm(n, log(70), 0.23)), 1)

# Add some missing data
dat$wt[sample.int(n, 5)] <- NA

# render
my.render.cont <- function (x, ...) {
  with(lapply(stats.default(x), # had digits=1,digits.pct=1
              round_pad, digits=2,digits.pct=2,round.median.min.max = F,round.integers = F, ...), 
       c("",
         `Mean (SD)`         = sprintf("%s (%s)", MEAN, SD))) # was %s for both
}

my.render.cat <- function(x) {
  c("", sapply(stats.default(x,round.median.min.max = F,round.integers = F),
               function(y) with(y, sprintf("%d (%0.2f %%)", FREQ, PCT))))
}

# OK but only one decimal in missing percentages
table1(~ age + sex + wt | treat, 
       data=dat,
       render.continuous=my.render.cont, 
       render.categorical=my.render.cat) 

# produces error..
table1(~ age + sex + wt | treat, 
       data=dat,
       render.continuous=my.render.cont, 
       render.categorical=my.render.cat,
       render.missing=my.render.cat)
#... Error in eval(substitute(expr), data, enclos = parent.frame()) :
# not that many frames on the stack

Also a a general documentation on how to customize the continous/categorical/missing renderings would be very helpful. Can make most things work but it is currently copy pasting things from here and there.

benjaminrich commented 1 year ago

I agree that better documentation would be helpful (I'll see what I can do). A simpler way to accomplish what you want (consistent 2 decimal places everywhere) without needing any render functions is:

table1(~ age + sex + wt | treat, data=dat,
    render.continuous    = c(.="Mean (SD)"),
    rounding.fn          = round_pad,
    round.median.min.max = FALSE,
    digits.pct           = 2,
    digits               = 2)

(edit: updated with simpler code)

samuelsaari commented 1 year ago

Ok thanks, this is nice and straightforward.