benjaminrich / table1

78 stars 26 forks source link

Interspaced Rtable1-zebra? #114

Closed SmartChen96 closed 8 months ago

SmartChen96 commented 8 months ago

Hi Benjaminrich,

Thanks for the powerful package for creating descriptive statistics. I am wondering if it is possible to let background filling be alternated for every other row when setting topclass="Rtable1-zebra". Due to the need to show only one-row continuous variable, the default format of shade rows for "Rtable1-zebra" seems incorrect. Thus, here comes this question.

image
benjaminrich commented 8 months ago

I'm not sure how you generated this, but I can't reproduce it. When I do it, it looks fine:

image

I used this code:

rndr <- function(x, name, ...) {
    stats <- c(.="Mean (SD)")
    if (name=="age") {
        stats <- c(.="Median [Min, Max]")
    }

    render.default(x, render.continuous=stats, ...)
}

table1(~ age + sex + wt | treat, data=dat, topclass="Rtable1-zebra", render=rndr)
SmartChen96 commented 8 months ago

Sorry to bother you with such a question. I've also just started using this function, and the issue seems to be resolved for now, although I'm not sure why it worked fine with a different dataset.

Additionally, I'd like to ask for your help with another issue: I've browsed through old posts and tried to set the decimal places for numbers and percentages in the table, but I'm not sure how to do that within the custom function 1:

rndr <- function(x, name, ...) {
  cont <- ifelse(name %in% vars.normal, "Mean (SD)", "Median (Q1 - Q3)")
  y <- render.default(x, name, render.continuous=cont, ...)
  if (is.logical(x)) {y[2]} 
  else if (is.factor(x) & length(levels(x))==2) {
    y[names(y) != levels(x)[1]] # Exclude the first (reference) level
  } else {y}
}

I found that it can be done in the render.continuousfunction like:

render.continuous <- function(x) {
    with(stats.default(x), 
         c("",

          "Mean (SD)" = sprintf("%s (%s)",
                                round_pad(MEAN, 1),
                                round_pad(SD, 1)),

          "Median (Min, Max)" = sprintf("%s (%s, %s)",
                                       round_pad(MEDIAN, 1), 
                                       round_pad(MIN, 1), 
                                       round_pad(MAX, 1)))
    )
}

but it seems that the two approaches conflict with each other. Of course, I'm also not clear on how to efficiently set the decimal places for both numbers and percentages at the same time. I also wonder if there is a more efficient way to set the same decimal places for numbers and percentages in one table. A custom function like function 1 allows for many special settings and changes, for me, is highly recommended.

benjaminrich commented 8 months ago

If I understand you correctly, you want to round all values to 1 decimal place, instead of the default (3 significant digits)?

You can do that by supplying digits=1, rounding.fn=round_pad inside table1(...).

SmartChen96 commented 8 months ago

Thx so much. Benjaminrich, it works well now. I appreciate your time and help!