This chapter builds the table by hand, directly with gt. That is worth doing for two reasons. Assembling a Table 1 a row group at a time is how you learn what is actually in one: which variables earn a row, which summary each variable type asks for, and where a reader expects the denominators. And gt is the right tool when the table’s destination is an HTML document, this book included, rather than a Word file bound for a journal.
That splits the work along a clean line: hand-built gt for understanding and for the web, the hv_*() functions in manuscript tables when it goes to a manuscript.
33.1 When to use it
Open almost any clinical manuscript and the first table you meet is a baseline-characteristics summary, the one journals number “Table 1.” It describes who was in the study before any outcome is discussed: how old the patients were, how their risk factors split, and whether the comparison groups looked alike at the start. Reach for it whenever you need to convince a reader that two arms are comparable, or simply to put a face on the cohort a figure later summarises. The job is description, not inference. A good Table 1 lets a reader decide for themselves whether a later result is believable, because they can see what the groups were made of.
The layout is always the same: rows of characteristics, columns split by the grouping variable (treatment, exposure, sex). Continuous variables get a centre and a spread (mean and standard deviation, or median and interquartile range); categorical variables get a count and a percentage. We build the table here from hvtiRutilities::generate_survival_data(), which returns a richly labelled patient-level cohort with a natural grouping variable (sex), so the recipe runs end to end before you point it at your own data. It is the same cohort describing a dataset took inventory of, so if you want to see where the variables below came from, that chapter is one click back.
A Table 1 is assembled one variable type at a time, then joined and rendered. We summarise the continuous variables first, the categorical variable second, and hand the combined frame to gt() for formatting. Doing it in pieces keeps each summary readable and lets you check the numbers before they are dressed up.
33.2.1 Summarise numeric variables as mean ± SD
We summarise three continuous baseline variables (age, BMI, baseline eGFR) as mean and standard deviation within each sex group. Mean and SD are the textbook pair when a variable is roughly symmetric; for a skewed variable (cost, time on bypass) you would report median and interquartile range instead, since a mean dragged by a long tail misrepresents the typical patient.
Know before you copy this that mean and SD are not what a CORR manuscript table reports. The house convention is a median with the 15th and 85th percentiles, whatever the shape, so that one summary covers the symmetric and the skewed variable alike and there is no per-variable normality call to defend to a reviewer. Manuscript tables builds the table that way and prints the footnote that documents it. We stay with mean and SD here because this chapter is assembling a table by hand for the web, and because holding the two conventions side by side is the fastest way to see what the house one buys you.
# A tibble: 2 × 8
sex n age_mean age_sd bmi_mean bmi_sd gfr_mean gfr_sd
<fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Female 77 45.1 14.8 27.1 4.89 76.6 20.5
2 Male 123 44.3 14.5 26.6 4.67 75.9 18.7
33.2.2 Summarise a categorical variable as n (%)
Diabetes status is summarised as a count and within-group percentage. The percentage here is within each sex group, the column denominator, which is almost always what a reader expects: “what fraction of the women had diabetes,” not “what fraction of all diabetics were women.” Make the denominator explicit in your own head before you compute it, because the same count divided by a different base tells a different story.
# A tibble: 2 × 3
sex diabetes_n diabetes_pct
<fct> <int> <dbl>
1 Female 17 22.1
2 Male 38 30.9
33.2.3 Render with gt()
We join the two summaries and present the result with a header, relabelled columns, and consistent numeric formatting. Mean ± SD pairs are formatted to one decimal place; the diabetes percentage to one decimal place.
The table renders as static HTML here, which is what gt is for. When the same numbers have to reach a journal, hand the summary to manuscript tables instead and let hvtiRtables place the footnotes and the abbreviation key where the CORR rules want them.
33.3 Pitfalls
Significance tests in Table 1. It is tempting to add a p-value column comparing the groups, and many journals still ask for one. In a randomised trial that column is close to meaningless: any baseline difference is by construction due to chance, so testing it asks whether randomisation worked, not whether the groups differ in a way that matters. In an observational cohort the test is at least answering a real question, but a small p-value on a tiny clinically irrelevant difference (a half-year age gap in 5,000 patients) misleads more than it informs. Describe the groups; let the reader judge balance from the numbers and the standardised differences.
Inconsistent rounding. Decide on decimal places per variable and hold to it down the whole column. Age to one decimal in one row and whole numbers in the next reads as carelessness and makes the eye work harder. fmt_number() with a fixed decimals keeps a column honest; the recipe above pins the continuous summaries and the percentage to one decimal each.
Ambiguous denominators for percentages. A percentage means nothing without its base. State whether it is computed within the column group, across the whole cohort, or among only the patients with a non-missing value, and be consistent. When missingness is common, report the n the percentage rests on so a reader does not assume a denominator you did not use.
Iannone, Richard, Joe Cheng, Barret Schloerke, et al. 2026. Gt: Easily Create Presentation-Ready Display Tables. https://gt.rstudio.com.