Skip to contents

Introduction

DescrTab2 is the replacement of the DescrTab package. It supports a variety of different customization options and can be used in .Rmd files in conjunction with knitr.

Preamble settings

DescrTab2 works in your R-console, as well as in .Rmd documents corresponding to output formats of the type pdf_documument, html_document and word_document. It even supports YAML-headers with multiple output formats! For example, if your YAML-header looks like the example below, DescrTab2 should automagically detect the output format depending on the rendering option you choose from the dropdown menue (the arrow next to the “Knit” button on the top menue bar).

---
title: "DescrTab2 tutorial"
output:
  word_document: default
  pdf_document: default
  html_document: default
---

Required LaTeX packages should be loaded automatically as well when rendering as a pdf.

Getting started

Make sure you include the DescrTab2 library by typing

somewhere in the document before you use it. You are now ready to go!

We will use two tidyverse libraries for data manipulation and a the following dataset for instructive purposes:

library(dplyr, warn.conflicts = FALSE)
library(forcats)
set.seed(123)
dat <- iris[, c("Species", "Sepal.Length")] |>
  mutate(animal = c("Mammal", "Fish") |> rep(75) |> factor()) |>
  mutate(food = c("fries", "wedges") |> sample(150, TRUE) |> factor())
head(dat)
#>   Species Sepal.Length animal   food
#> 1  setosa          5.1 Mammal  fries
#> 2  setosa          4.9   Fish  fries
#> 3  setosa          4.7 Mammal  fries
#> 4  setosa          4.6   Fish wedges
#> 5  setosa          5.0 Mammal  fries
#> 6  setosa          5.4   Fish wedges

Producing beautiful descriptive tables is now as easy as typing:

descr(dat)
Variable
Total
p
(N=150)
Species
setosa 50 (33.3%) >0.999chi1
versicolor 50 (33.3%)
virginica 50 (33.3%)
Sepal.Length
N 150 tt1
mean 5.84
sd 0.828
median 5.8
Q1 - Q3 5.1 – 6.4
min - max 4.3 – 7.9
animal
Fish 75 (50.0%) >0.999chi1
Mammal 75 (50.0%)
food
fries 76 (50.7%) 0.870chi1
wedges 74 (49.3%)
chi1 Chi-squared goodness-of-fit test
tt1 Student’s one-sample t-test

Accessing table elements

The object returned from the descr function is basically just a named list. You may be interested in referencing certain summary statistics from the table in your document. To do this, you can save the list returned by descr:

my_table <- descr(dat)

You can then access the elements of the list using the $ operator.

my_table$variables$Sepal.Length$results$Total$mean
#> NULL

Rstudios autocomplete suggestions are very helpful when navigating this list.

The print function returns a formatted version of this list, which you can also save and access using the same syntax.

my_table <- descr(dat) |> print(silent=TRUE)

Specifying a group

Use the group option to specify the name of a grouping variable in your data:

descr(dat, "Species")
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
Sepal.Length
N 50 50 50 150 F
mean 5.01 5.94 6.59 5.84
sd 0.352 0.516 0.636 0.828
median 5 5.9 6.5 5.8
Q1 - Q3 4.8 – 5.2 5.6 – 6.3 6.2 – 6.9 5.1 – 6.4
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
animal
Fish 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%) >0.999chi2
Mammal 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%)
food
fries 30 (60.0%) 27 (54.0%) 19 (38.0%) 76 (50.7%) 0.075chi2
wedges 20 (40.0%) 23 (46.0%) 31 (62.0%) 74 (49.3%)
F F-test (ANOVA)
chi2 Pearson’s chi-squared test

Assigning labels

Use the group_labels option to assign group labels and the var_labels option to assign variable labels:

descr(dat, "Species", group_labels=list(setosa="My custom group label"), var_labels = list(Sepal.Length = "My custom variable label"))
Variable
My custom group label
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
My custom variable label
N 50 50 50 150 F
mean 5.01 5.94 6.59 5.84
sd 0.352 0.516 0.636 0.828
median 5 5.9 6.5 5.8
Q1 - Q3 4.8 – 5.2 5.6 – 6.3 6.2 – 6.9 5.1 – 6.4
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
animal
Fish 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%) >0.999chi2
Mammal 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%)
food
fries 30 (60.0%) 27 (54.0%) 19 (38.0%) 76 (50.7%) 0.075chi2
wedges 20 (40.0%) 23 (46.0%) 31 (62.0%) 74 (49.3%)
F F-test (ANOVA)
chi2 Pearson’s chi-squared test

Assigning a table caption

Use the caption member of the format_options argument to assign a table caption:

descr(dat, "Species", format_options = list(caption="Description of our example dataset."))
Description of our example dataset.
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
Sepal.Length
N 50 50 50 150 F
mean 5.01 5.94 6.59 5.84
sd 0.352 0.516 0.636 0.828
median 5 5.9 6.5 5.8
Q1 - Q3 4.8 – 5.2 5.6 – 6.3 6.2 – 6.9 5.1 – 6.4
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
animal
Fish 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%) >0.999chi2
Mammal 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%)
food
fries 30 (60.0%) 27 (54.0%) 19 (38.0%) 76 (50.7%) 0.075chi2
wedges 20 (40.0%) 23 (46.0%) 31 (62.0%) 74 (49.3%)
F F-test (ANOVA)
chi2 Pearson’s chi-squared test

Confidence intervals for two group comparisons

For 2-group comparisons, DescrTab2 automatically calculates confidence intervals for differences in effect measures:

descr(dat, "animal")
Variable
Fish
Mammal
Total
p
(N=75) (N=75) (N=150)
Species
setosa 25 (33.3%) 25 (33.3%) 50 (33.3%) >0.999chi2
versicolor 25 (33.3%) 25 (33.3%) 50 (33.3%)
virginica 25 (33.3%) 25 (33.3%) 50 (33.3%)
Sepal.Length
N 75 75 150 0.961tt2
mean 5.85 5.84 5.84
sd 0.855 0.806 0.828
median 5.7 5.8 5.8
Q1 - Q3 5.1 – 6.4 5.1 – 6.5 5.1 – 6.4
min - max 4.3 – 7.9 4.4 – 7.7 4.3 – 7.9
food
fries 37 (49.3%) 39 (52.0%) 76 (50.7%) 0.744chi2
wedges 38 (50.7%) 36 (48.0%) 74 (49.3%)
chi2 Pearson’s chi-squared test
tt2 Welch’s two-sample t-test

Different tests

There are a lot of different tests available. Check out the test_choice vignette for details: https://imbi-heidelberg.github.io/DescrTab2/articles/b_test_choice_tree_pdf.pdf

Here are some different tests in action:

descr(dat |> select(-"Species"), "animal", test_options = list(exact=TRUE, nonparametric=TRUE))
Variable
Fish
Mammal
Total
p
(N=75) (N=75) (N=150)
Sepal.Length
N 75 75 150 0.870MWU
mean 5.85 5.84 5.84
sd 0.855 0.806 0.828
median 5.7 5.8 5.8
Q1 - Q3 5.1 – 6.4 5.1 – 6.5 5.1 – 6.4
min - max 4.3 – 7.9 4.4 – 7.7 4.3 – 7.9
food
fries 37 (49.3%) 39 (52.0%) 76 (50.7%) 0.803Bolo
wedges 38 (50.7%) 36 (48.0%) 74 (49.3%)
MWU Mann-Whitney’s U test
Bolo Boschloo’s test
descr(dat |> select(c("Species", "Sepal.Length")), "Species", test_options = list(nonparametric=TRUE))
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
Sepal.Length
N 50 50 50 150 KW
mean 5.01 5.94 6.59 5.84
sd 0.352 0.516 0.636 0.828
median 5 5.9 6.5 5.8
Q1 - Q3 4.8 – 5.2 5.6 – 6.3 6.2 – 6.9 5.1 – 6.4
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
KW Kruskal-Wallis’s one-way ANOVA

Paired observations

In situations with paired data, the group variable usually denotes the timing of the measurement (e.g. “before” and “after” or “time 1”, “time 2”, etc.). In these scenarios, you need an additional index variable that specifies which observations from the different timepoints should be paired. The test_options =list(paired=TRUE, indices = <Character name of index variable name or vector of indices>) option can be used to specify the pairing indices, see the example below. DescrTab2 only works with data in “long format”, see e.g. ?reshape or ?tidyr::pivot_longer for information on how to transoform your data from wide to long format.

descr(dat |> mutate(animal = fct_recode(animal, Before="Fish", After="Mammal")) |> select(-"Species"), "animal", test_options = list(paired=TRUE, indices=rep(1:75, each=2)))
#> You specified paired tests and did not explicitly
#> specify format_options$print_Total. print_Total is set to FALSE.
#> Warning in sig_test(var, group, test_options, test_override, var_name): Confidence intervals for differences in proportions ignore the paired structure of the data.
#> Use Exact McNemar's test if you want confidence intervals which use the test statistic of the
#> exact McNemar's test.
Variable
Before
After
p
(N=75) (N=75)
Sepal.Length
N 75 75 0.937tpar
mean 5.85 5.84
sd 0.855 0.806
median 5.7 5.8
Q1 - Q3 5.1 – 6.4 5.1 – 6.5
min - max 4.3 – 7.9 4.4 – 7.7
food
fries 37 (49.3%) 39 (52.0%) 0.877McN
wedges 38 (50.7%) 36 (48.0%)
tpar Student’s paired t-test
McN McNemar’s test

descr(dat |> mutate(animal = fct_recode(animal, Before="Fish", After="Mammal"), idx = rep(1:75, each=2)) |> select(-"Species"), "animal", test_options = list(paired=TRUE, indices="idx" ))
#> You specified paired tests and did not explicitly
#> specify format_options$print_Total. print_Total is set to FALSE.
#> Warning in sig_test(var, group, test_options, test_override, var_name): Confidence intervals for differences in proportions ignore the paired structure of the data.
#> Use Exact McNemar's test if you want confidence intervals which use the test statistic of the
#> exact McNemar's test.
Variable
Before
After
p
(N=75) (N=75)
Sepal.Length
N 75 75 0.937tpar
mean 5.85 5.84
sd 0.855 0.806
median 5.7 5.8
Q1 - Q3 5.1 – 6.4 5.1 – 6.5
min - max 4.3 – 7.9 4.4 – 7.7
food
fries 37 (49.3%) 39 (52.0%) 0.877McN
wedges 38 (50.7%) 36 (48.0%)
tpar Student’s paired t-test
McN McNemar’s test

Significant digits

Every summary statistic in DescrTab2 is formatted by a corresponding formatting function. You can exchange these formatting functions as you please:

descr(dat, "Species", format_summary_stats = list(mean=function(x)formatC(x, digits = 4)) )
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
Sepal.Length
N 50 50 50 150 F
mean 5.006 5.936 6.588 5.843
sd 0.352 0.516 0.636 0.828
median 5 5.9 6.5 5.8
Q1 - Q3 4.8 – 5.2 5.6 – 6.3 6.2 – 6.9 5.1 – 6.4
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
animal
Fish 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%) >0.999chi2
Mammal 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%)
food
fries 30 (60.0%) 27 (54.0%) 19 (38.0%) 76 (50.7%) 0.075chi2
wedges 20 (40.0%) 23 (46.0%) 31 (62.0%) 74 (49.3%)
F F-test (ANOVA)
chi2 Pearson’s chi-squared test

Omitting summary statistics

Let’s say you don’t want to calculate quantiles for your numeric variables. You can specify the summary_stats_cont option to include all summary statistics but quantiles:

descr(dat, "Species", summary_stats_cont = list(N = DescrTab2:::.N, Nmiss = DescrTab2:::.Nmiss, mean =
    DescrTab2:::.mean, sd = DescrTab2:::.sd, median = DescrTab2:::.median, min = DescrTab2:::.min, max =
    DescrTab2:::.max))
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
Sepal.Length
N 50 50 50 150 F
mean 5.01 5.94 6.59 5.84
sd 0.352 0.516 0.636 0.828
median 5 5.9 6.5 5.8
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
animal
Fish 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%) >0.999chi2
Mammal 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%)
food
fries 30 (60.0%) 27 (54.0%) 19 (38.0%) 76 (50.7%) 0.075chi2
wedges 20 (40.0%) 23 (46.0%) 31 (62.0%) 74 (49.3%)
F F-test (ANOVA)
chi2 Pearson’s chi-squared test

Adding summary statistics

Let’s say you have a categorical variable, but for some reason it’s levels are numerals and you want to calculate the mean. No problem:

# Create example dataset
dat2 <- iris
dat2$cat_var <- c(1,2) |> sample(150, TRUE) |> factor()
dat2 <- dat2[, c("Species", "cat_var")]

descr(dat2, "Species", summary_stats_cat=list(mean=DescrTab2:::.factormean))
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
cat_var
mean 1.46 1.6 1.38 1.48 0.083chi2
1 27 (54.0%) 20 (40.0%) 31 (62.0%) 78 (52.0%)
2 23 (46.0%) 30 (60.0%) 19 (38.0%) 72 (48.0%)
chi2 Pearson’s chi-squared test

Combining mean and sd

Use the format_options = list(combine_mean_sd=TRUE) option:

descr(dat, "Species", format_options = c(combine_mean_sd=TRUE))
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
Sepal.Length
N 50 50 50 150 F
mean ± sd 5.01 ± 0.352 5.94 ± 0.516 6.59 ± 0.636 5.84 ± 0.828
median 5 5.9 6.5 5.8
Q1 - Q3 4.8 – 5.2 5.6 – 6.3 6.2 – 6.9 5.1 – 6.4
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
animal
Fish 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%) >0.999chi2
Mammal 25 (50.0%) 25 (50.0%) 25 (50.0%) 75 (50.0%)
food
fries 30 (60.0%) 27 (54.0%) 19 (38.0%) 76 (50.7%) 0.075chi2
wedges 20 (40.0%) 23 (46.0%) 31 (62.0%) 74 (49.3%)
F F-test (ANOVA)
chi2 Pearson’s chi-squared test

Omitting p-values

You can declare the format_options = list(print_p = FALSE) option to omit p-values:

descr(dat, "animal", format_options = list(print_p = FALSE))
Variable
Fish
Mammal
Total
(N=75) (N=75) (N=150)
Species
setosa 25 (33.3%) 25 (33.3%) 50 (33.3%)
versicolor 25 (33.3%) 25 (33.3%) 50 (33.3%)
virginica 25 (33.3%) 25 (33.3%) 50 (33.3%)
Sepal.Length
N 75 75 150
mean 5.85 5.84 5.84
sd 0.855 0.806 0.828
median 5.7 5.8 5.8
Q1 - Q3 5.1 – 6.4 5.1 – 6.5 5.1 – 6.4
min - max 4.3 – 7.9 4.4 – 7.7 4.3 – 7.9
food
fries 37 (49.3%) 39 (52.0%) 76 (50.7%)
wedges 38 (50.7%) 36 (48.0%) 74 (49.3%)

Similarily for Confidence intervals:

descr(dat, "animal", format_options = list(print_CI = FALSE))
Variable
Fish
Mammal
Total
p
(N=75) (N=75) (N=150)
Species
setosa 25 (33.3%) 25 (33.3%) 50 (33.3%) >0.999chi2
versicolor 25 (33.3%) 25 (33.3%) 50 (33.3%)
virginica 25 (33.3%) 25 (33.3%) 50 (33.3%)
Sepal.Length
N 75 75 150 0.961tt2
mean 5.85 5.84 5.84
sd 0.855 0.806 0.828
median 5.7 5.8 5.8
Q1 - Q3 5.1 – 6.4 5.1 – 6.5 5.1 – 6.4
min - max 4.3 – 7.9 4.4 – 7.7 4.3 – 7.9
food
fries 37 (49.3%) 39 (52.0%) 76 (50.7%) 0.744chi2
wedges 38 (50.7%) 36 (48.0%) 74 (49.3%)
chi2 Pearson’s chi-squared test
tt2 Welch’s two-sample t-test

Controling options on a per-variable level

You can use the var_options list to control formatting and test options on a per-variable basis. Let’s say in the dataset iris, we want that only the Sepal.Length variable has more digits in the mean and a nonparametric test:

descr(iris, "Species", var_options = list(Sepal.Length = list(
  format_summary_stats = list(
    mean = function(x)
      formatC(x, digits = 4)
  ),
  test_options = c(nonparametric = TRUE)
)))
Variable
setosa
versicolor
virginica
Total
p
(N=50) (N=50) (N=50) (N=150)
Sepal.Length
N 50 50 50 150 KW
mean 5.006 5.936 6.588 5.843
sd 0.352 0.516 0.636 0.828
median 5 5.9 6.5 5.8
Q1 - Q3 4.8 – 5.2 5.6 – 6.3 6.2 – 6.9 5.1 – 6.4
min - max 4.3 – 5.8 4.9 – 7 4.9 – 7.9 4.3 – 7.9
Sepal.Width
N 50 50 50 150 F
mean 3.43 2.77 2.97 3.06
sd 0.379 0.314 0.322 0.436
median 3.4 2.8 3 3
Q1 - Q3 3.2 – 3.7 2.5 – 3 2.8 – 3.2 2.8 – 3.3
min - max 2.3 – 4.4 2 – 3.4 2.2 – 3.8 2 – 4.4
Petal.Length
N 50 50 50 150 F
mean 1.46 4.26 5.55 3.76
sd 0.174 0.47 0.552 1.77
median 1.5 4.35 5.55 4.35
Q1 - Q3 1.4 – 1.6 4 – 4.6 5.1 – 5.9 1.6 – 5.1
min - max 1 – 1.9 3 – 5.1 4.5 – 6.9 1 – 6.9
Petal.Width
N 50 50 50 150 F
mean 0.246 1.33 2.03 1.2
sd 0.105 0.198 0.275 0.762
median 0.2 1.3 2 1.3
Q1 - Q3 0.2 – 0.3 1.2 – 1.5 1.8 – 2.3 0.3 – 1.8
min - max 0.1 – 0.6 1 – 1.8 1.4 – 2.5 0.1 – 2.5
KW Kruskal-Wallis’s one-way ANOVA
F F-test (ANOVA)

Use user defined test statistics

DescrTab2 has many predefined significance tests, but sometimes you may need to use a custom test. In this case, you can use the test_override option in test_options (or as a part of per variable options, see above). To do so, test_override must be a list with at least 3 members:

  • the name of the test (e.g. “custom t-test”)
  • an abbreviation for this name (e.g. “ct”)
  • a function that takes the variable to be analysed and possibly a group variable and returns the p-value.
custom_ttest <- list(
  name = "custom t-test",
  abbreviation = "ct",
  p = function(var) {
    return(t.test(var, alternative = "greater")$p.value)
  }
)

descr(iris |> select(-Species), test_options = list(test_override = custom_ttest))
Variable
Total
p
(N=150)
Sepal.Length
N 150 ct
mean 5.84
sd 0.828
median 5.8
Q1 - Q3 5.1 – 6.4
min - max 4.3 – 7.9
Sepal.Width
N 150 ct
mean 3.06
sd 0.436
median 3
Q1 - Q3 2.8 – 3.3
min - max 2 – 4.4
Petal.Length
N 150 ct
mean 3.76
sd 1.77
median 4.35
Q1 - Q3 1.6 – 5.1
min - max 1 – 6.9
Petal.Width
N 150 ct
mean 1.2
sd 0.762
median 1.3
Q1 - Q3 0.3 – 1.8
min - max 0.1 – 2.5
ct custom t-test

Supress the last factor level

If you have a lot of binary factors, you may want to suppress one of the factor levels to save space. A common use case for this practise is when you analyse questionaires with a great deal of “yes” / “no” items. You can do so by setting the omit_factor_level option to either "first" or "last".

descr(factor(c("a", "b")), format_options=list(omit_factor_level = "last"))
#> Warning in (function (x, y = NULL, correct = TRUE, p = rep(1/length(x), :
#> Chi-squared approximation may be incorrect
Variable
Total
p
(N=2)
value
a 1 (50.0%) >0.999chi1
chi1 Chi-squared goodness-of-fit test

Confidence intervals as summary statistics

Sometimes it may be a good idea to show the confidence intervals as summary statistics. To do so, you can supply appropriate summary statistics for the confidence intervals with corresponding formatting functions. DescrTab2 offers the following predefined CI functions:

  • DescrTab2:::.meanCIlower
  • DescrTab2:::.meanCIupper
  • DescrTab2:::.factor_firstlevel_CIlower
  • DescrTab2:::.factor_firstlevel_CIupper
  • DescrTab2:::.factor_lastlevel_CIlower
  • DescrTab2:::.factor_lastlevel_CIupper
  • DescrTab2:::.HLCIlower
  • DescrTab2:::.HLCIupper
summary_stats_cat <- list(
  CIL = DescrTab2:::.factor_firstlevel_CIlower,
  CIU = DescrTab2:::.factor_firstlevel_CIupper)

summary_stats_cont  <-  list(
  N = DescrTab2:::.N,
  Nmiss = DescrTab2:::.Nmiss,
  mean = DescrTab2:::.mean,
  sd = DescrTab2:::.sd,
  CILM = DescrTab2:::.meanCIlower,
  CIUM = DescrTab2:::.meanCIupper)

format_summary_stats <- list(
  CIL = scales::label_percent(),
  CIU = scales::label_percent(),
  CILM = function(x) format(x, digits = 2, scientific = 3),
  CIUM = function(x) format(x, digits = 2, scientific = 3),
  N = function(x) {
    format(x, digits = 2, scientific = 3)
  },
  mean = function(x) {
    format(x, digits = 2, scientific = 3)
  },
  sd = function(x) {
    format(x, digits = 2, scientific = 3)
  },
  CI = function(x) {
    format(x, digits = 2, scientific = 3)
  }
)

reshape_rows <- list(
  `CI` = list(
    args = c("CIL", "CIU"),
    fun = function(CIL, CIU) {
      paste0("[", CIL, ", ", CIU, "]")
    }
  ),
  `CI` = list(
    args = c("CILM", "CIUM"),
    fun = function(CILM, CIUM) {
      paste0("[", CILM, ", ", CIUM, "]")
    }
  )
)

set.seed(123)
dat <- tibble(a_factor = factor(c(rep("a", 70), rep("b", 30))),
              a_numeric = rnorm(100),
              group = sample(c("Trt", "Ctrl"), 100, TRUE)
)

descr(dat, "group",
  format_options=list(omit_factor_level = "last",
  categories_first_summary_stats_second = FALSE,
  combine_mean_sd = TRUE
  ),
  summary_stats_cat = summary_stats_cat,
  summary_stats_cont = summary_stats_cont,
  reshape_rows = reshape_rows,
  format_summary_stats = format_summary_stats)
Variable
Ctrl
Trt
Total
p
(N=49) (N=51) (N=100)
a_factor
CI [63%, 88%] [48%, 76%] [60%, 79%] 0.106chi2
a 38 (77.6%) 32 (62.7%) 70 (70.0%)
a_numeric
N 49 51 100 0.122tt2
mean ± sd 0.23 ± 0.88 -0.048 ± 0.93 0.09 ± 0.91
CI [-0.019, 0.49] [-0.31, 0.21] [-0.091, 0.27]
chi2 Pearson’s chi-squared test
tt2 Welch’s two-sample t-test