Builds a publication-ready frequency or cross-tabulation table for one or many categorical variables selected with tidyselect syntax.
With by, produces grouped cross-tabulation summaries (using
cross_tab() internally) with Chi-squared p-values and optional
association measures.
Without by, produces one-way frequency-style summaries.
Multiple output formats are available via output: a printed ASCII
table ("default"), a wide or long numeric data.frame
("data.frame", "long"), or publication-ready tables
("tinytable", "gt", "flextable", "excel", "clipboard",
"word").
Usage
table_categorical(
data,
select = tidyselect::everything(),
by = NULL,
labels = NULL,
levels_keep = NULL,
include_total = TRUE,
drop_na = FALSE,
weights = NULL,
rescale = FALSE,
correct = FALSE,
simulate_p = FALSE,
simulate_B = 2000,
percent_digits = 1,
p_digits = 3,
v_digits = 2,
assoc_measure = "auto",
assoc_ci = FALSE,
decimal_mark = ".",
align = c("decimal", "center", "right"),
output = c("default", "data.frame", "long", "tinytable", "gt", "flextable", "excel",
"clipboard", "word"),
indent_text = " ",
indent_text_excel_clipboard = strrep(" ", 6),
add_multilevel_header = TRUE,
blank_na_wide = FALSE,
excel_path = NULL,
excel_sheet = "Categorical",
clipboard_delim = "\t",
word_path = NULL,
user_na = TRUE
)Arguments
- data
A data frame.
- select
Columns to include as row variables. Supports tidyselect syntax and character vectors of column names. When omitted, defaults to every eligible categorical column in
data: factor, character, logical, and labelled (haven/labelled) columns, excluding thebycolumn – matching the select-less defaults oftable_continuous()andtable_continuous_lm(). An explicitselectis taken verbatim (numeric columns included), so numeric-coded categorical variables can still be tabulated by naming them.- by
Optional grouping column used for columns/groups. Accepts an unquoted column name or a single character column name. Factor levels keep their declared order; any other
by(character, numeric, haven labelled) forms group columns in order of first appearance in the data – the same convention astable_continuous(). For a haven labelledby, the group headers are the raw codes (value labels are not used for group headers – the family convention shared withtable_continuous()andtable_continuous_lm()); declared missing values followuser_naas usual.- labels
An optional named character vector of variable labels whose names match column names in
data(e.g.c(smoking = "Current smoker")) – the same contract astable_continuous()andtable_continuous_lm(). Only listed columns are relabelled. For the remaining columns (and whenlabels = NULL, the default), labels are auto-detected from the variable's label attribute (e.g. fromhaven); if none is found, the column name is used. Unnamed (positional) label vectors, accepted before 0.13.0, now raise an error.- levels_keep
Optional character vector of levels to keep/order for row modalities. If
NULL, all observed levels are kept. Entries must match the level strings the table displays (for labelled columns these are the"[code] label"strings, not the bare label text). When nothing matches for a selected variable, that variable is dropped from the table with a classed warning (spicy_no_selection) listing the available level strings.- include_total
Logical. If
TRUE(the default), includes aTotalgroup when available.- drop_na
Logical. If
FALSE(the default), missing values are displayed as a dedicated"(Missing)"level (and, underby, a"(Missing)"group column) – the field convention for descriptive tables (gtsummary's "Unknown" row, janitor'sNArow; see the Epidemiologist R Handbook, Descriptive tables). IfTRUE, rows withNAin the tabulated variable (and inby, when supplied) are removed BEFORE each cross-tabulation, and the removal is disclosed in a table note ("Missing values removed: ...") rather than silent. Before 0.13.0 the default wasTRUEwith no disclosure.- weights
Optional weights. Either
NULL(the default), a numeric vector of lengthnrow(data), or a single column indatasupplied as an unquoted name or a character string.- rescale
Logical. If
FALSE(the default), weights are used as-is. IfTRUE, rescales weights so total weighted N matches raw N. Passed tospicy::cross_tab(). When the argument is not supplied, the default is read fromoptions(spicy.rescale)(falling back toFALSE), matchingcross_tab().- correct
Logical. If
FALSE(the default), no continuity correction is applied. IfTRUE, applies Yates correction in 2x2 chi-squared contexts. Passed tospicy::cross_tab().- simulate_p
Logical. If
FALSE(the default), uses asymptotic p-values. IfTRUE, uses Monte Carlo simulation. Passed tospicy::cross_tab().- simulate_B
Integer. Number of Monte Carlo replicates when
simulate_p = TRUE. Defaults to2000.- percent_digits
Number of digits for percentages in report outputs. Defaults to
1.- p_digits
Integer >= 1. Number of decimal places used to render p-values in the
pcolumn (default:3, the APA Publication Manual standard). Both the displayed precision and the small-p threshold derive from this argument:p_digits = 3prints.045and<.001;p_digits = 4prints.0451and<.0001. Leading zeros are always stripped, following APA convention.- v_digits
Number of digits for the association measure. Defaults to
2.- assoc_measure
Which association measure to report alongside the chi-squared p-value. Accepts four input shapes:
"none"– drop the column entirely."auto"(the default) – pick a measure per row variable based on the variable type: a 2x2 table (binary row variable vs. binaryby) usesphi, a pair of ordered factors usestau_b, every other case usescramer_v.a single string from
c("cramer_v", "phi", "gamma", "tau_b", "tau_c", "somers_d", "lambda")– applied uniformly to every row variable.a character vector with one entry per row variable. Both named (
c(smoking = "phi", health = "tau_b"), recommended; unnamed variables fall back to"auto") and unnamed positional (c("phi", "tau_b", "auto"), paired up withselect) are accepted. Named is more robust to reordering ofselect.
When a single measure is used for every row, the column header is that measure's name (e.g.
"Cramer's V"). When multiple measures are used (typically with"auto"on a heterogeneousselect), the header collapses to"Effect size"and an APA-styleNote.line is appended documenting which measure was used for which variable.phirequires a 2x2 table; if explicitly requested for a non-2x2 variable, an error is raised so the user can choose another measure or fall back to"auto".- assoc_ci
Passed to
cross_tab(). IfTRUE, includes the confidence interval of the association measure. In wide raw outputs ("data.frame","excel","clipboard"), two extra columnsCI lower/CI upperare added; in the long raw output ("long") the bounds appear asci_lower/ci_upper. In rendered formats ("gt","tinytable","flextable","word"), the CI is shown inline (e.g.,.14 [.08, .19]). Defaults toFALSE.- decimal_mark
Decimal separator (
"."or","). Defaults to".".- align
Horizontal alignment of numeric columns in the printed ASCII table and in the
tinytable,gt,flextable,word, andclipboardoutputs. The first column (Variable) is always left-aligned. One of:"decimal"(default): align numeric columns on the decimal mark, the standard scientific-publication convention used by SPSS, SAS, and LaTeXsiunitx. Numeric cells are pre-padded with figure-spaces (U+2007, digit-width) so every string in a column has the same width with the decimal mark at the same internal position; centring those uniform-width strings then stacks the decimal points vertically. The same pad-then-centre strategy is applied on every engine (gt,tinytable,flextable,word,clipboard, ASCII print) for a homogeneous rendering, matchingtable_regression()andtable_continuous_lm()."center": center-align all numeric columns."right": right-align all numeric columns.
The
exceloutput uses the engine's default alignment in any case: cell-string padding does not align decimals under proportional fonts, and Excel's native right-alignment combined with the per-columnnumfmtalready produces dot-aligned columns. Same default and semantics astable_continuous()/table_continuous_lm().- output
Output format. One of:
"default"(a printed ASCII table, returned invisibly)"data.frame"(a wide numericdata.frame)"long"(a long numericdata.frame)"tinytable"(requirestinytable)"gt"(requiresgt)"flextable"(requiresflextable)"excel"(requiresopenxlsx2)"clipboard"(requiresclipr)"word"(requiresflextableandofficer)
- indent_text
Prefix used for modality labels in report table building. Defaults to
" "(two spaces).- indent_text_excel_clipboard
Stronger indentation used in Excel and clipboard exports. Defaults to six non-breaking spaces.
- add_multilevel_header
Logical. If
TRUE(the default), merges top headers in Excel export. Only consulted foroutput = "excel"on a grouped table (bysupplied); like the other output-scoped presentation arguments (excel_sheet,clipboard_delim, ...), it is silently unused in every other output and in one-way tables, which have a single header row to begin with.- blank_na_wide
Logical. If
FALSE(the default),NAvalues are kept as-is in wide raw output. IfTRUE, replaces them with empty strings.- excel_path
Path for
output = "excel". Defaults toNULL.- excel_sheet
Sheet name for Excel export. Defaults to
"Categorical".- clipboard_delim
Delimiter for clipboard text export. Defaults to
"\t".- word_path
File path for
output = "word". Defaults toNULL. Before 0.13.0, supplying it withoutput = "flextable"also wrote a.docxas a side effect; it is now used exclusively byoutput = "word"(the contract shared with the rest of the table family) and is ignored, with a warning, underoutput = "flextable".- user_na
Logical. If
TRUE(the default), declared missing values in the row variables and inbyare treated as missing: they join the"(Missing)"level underdrop_na = FALSE, and underdrop_na = TRUEthey are removed with a dedicated disclosure line (Declared missing values removed: ...). IfFALSE, the declared codes stay valid categories. See the "Declared missing values" section offreq().
Value
Depends on output:
"default": prints a styled ASCII table and returns the underlyingdata.frameinvisibly (S3 class"spicy_categorical_table")."data.frame": a widedata.framewith one row per variable–level combination. Whenbyis used, the columns areVariable,Level, and one pair ofn/\%columns per group level (plusTotalwheninclude_total = TRUE), followed byChi2,df,p, and the association measure column. Whenby = NULL, the columns areVariable,Level,n,\%."long": a longdata.framewith columnsvariable,level,n,pct(plusgroup,chi2,df,p, and the association measure column whenbyis used)."tinytable": atinytableobject."gt": agt_tblobject."flextable": aflextableobject."excel"/"word": writes to disk and returns the file path invisibly."clipboard": copies the table and returns the displaydata.frameinvisibly.
Tests
When by is used, each selected variable is cross-tabulated
against the grouping variable with cross_tab() and the omnibus
chi-squared p-value is reported in the p column. See
@param correct / simulate_p to switch on Yates' continuity
correction or Monte Carlo p-values, and @param assoc_measure
for the per-row dispatch table used by "auto" (2x2 -> Phi,
both ordered -> Kendall's Tau-b, otherwise Cramer's V). Without
by, the table reports the marginal frequency distribution of
each variable with no inferential statistics.
For model-based comparisons (cluster-robust SE, weighted contrasts,
fitted means) on continuous outcomes, see table_continuous_lm().
For descriptive (empirical) comparisons on continuous outcomes, see
table_continuous().
Display conventions
Decimal alignment, p-value formatting, and required suggested
packages per output engine are documented under @param align,
@param p_digits, and @param output respectively.
Counts are displayed as integers: weighted counts are rounded
(ties half to even, the R convention) at display time only, in
cells and margins alike – the SPSS Crosstabs convention. Cells
and margins are rounded independently, so small display
discrepancies are possible (e.g. two cells of exactly 0.5 each
display as 0 while their Total of 1.0 displays as 1). The
machine outputs ("data.frame", "long") carry the exact
weighted counts and full-precision percentages.
Declared missing values
Survey files imported with haven often carry declared missing
values: codes such as 8 = Don't know or 9 = Refused that the
source file marks as missing while keeping them distinct from a
plain NA. Two kinds of declaration exist: na_values / na_range
metadata on haven::labelled_spss() vectors, and tagged missing
values created by haven::tagged_na() (the Stata .a, .b, ...
convention).
spicy honors the declaration by default (user_na = TRUE):
declared missing values are excluded from every statistic exactly
like NA – valid percentages, means, chi-squared tests,
association measures, row-wise summaries, and group definitions –
but they are not erased from display. freq() lists each observed
declared value as its own row of the Missing block, with its value
label; cross_tab(), table_categorical(), and
table_continuous() disclose the exclusion in the table note
(Declared missing values removed: x (2).); varlist() and
code_book() count them as missing in N_valid / NAs /
N_distinct while still listing the declared codes in Values.
Every function involved offers the same escape hatch: set
user_na = FALSE to ignore the declaration and treat the declared
codes as valid values (the behavior of spicy before 0.13.0).
Tagged missing values are genuine NAs either way; for them,
user_na = FALSE only collapses the per-tag breakdown back into
the regular NA count.
See also
table_continuous() for empirical comparisons on
continuous outcomes; table_continuous_lm() for the model-based
companion (heteroskedasticity-consistent / cluster-robust /
bootstrap / jackknife SE, fitted means, weighted contrasts);
cross_tab() for two-way cross-tabulations; freq() for
one-way frequency tables.
Other spicy tables:
table_continuous(),
table_continuous_lm()
Examples
# --- Basic usage ---------------------------------------------------------
# Default: ASCII console table grouped by sex.
table_categorical(
sochealth,
select = c(smoking, physical_activity),
by = sex
)
#> Categorical table by sex
#>
#> Variable │ Female n Female % Male n Male % Total n
#> ───────────────────────────┼─────────────────────────────────────────────
#> Current smoker │
#> No │ 475 76.6 451 77.8 926
#> Yes │ 131 21.1 118 20.3 249
#> (Missing) │ 14 2.3 11 1.9 25
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Regular physical activity │
#> No │ 334 53.9 316 54.5 650
#> Yes │ 286 46.1 264 45.5 550
#>
#> Variable │ Total % p Phi
#> ───────────────────────────┼────────────────────
#> Current smoker │ .713 .01
#> No │ 77.2
#> Yes │ 20.8
#> (Missing) │ 2.1
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Regular physical activity │ .832 .01
#> No │ 54.2
#> Yes │ 45.8
# One-way frequency-style table (no `by`).
table_categorical(
sochealth,
select = c(smoking, physical_activity)
)
#> Categorical table
#>
#> Variable │ n %
#> ─────────────────────────────┼───────────────
#> Current smoker │
#> No │ 926 77.2
#> Yes │ 249 20.8
#> (Missing) │ 25 2.1
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Regular physical activity │
#> No │ 650 54.2
#> Yes │ 550 45.8
# Pretty labels keyed by column name.
table_categorical(
sochealth,
select = c(smoking, physical_activity),
by = education,
labels = c(
smoking = "Current smoker",
physical_activity = "Physical activity"
)
)
#> Categorical table by education
#>
#> Variable │ Lower secondary n Lower secondary % Upper secondary n
#> ───────────────────┼─────────────────────────────────────────────────────────
#> Current smoker │
#> No │ 179 68.6 415
#> Yes │ 78 29.9 112
#> (Missing) │ 4 1.5 12
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Physical activity │
#> No │ 177 67.8 310
#> Yes │ 84 32.2 229
#>
#> Variable │ Upper secondary % Tertiary n Tertiary % Total n
#> ───────────────────┼────────────────────────────────────────────────────
#> Current smoker │
#> No │ 77.0 332 83.0 926
#> Yes │ 20.8 59 14.8 249
#> (Missing) │ 2.2 9 2.2 25
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Physical activity │
#> No │ 57.5 163 40.8 650
#> Yes │ 42.5 237 59.2 550
#>
#> Variable │ Total % p Cramer's V
#> ───────────────────┼────────────────────────────
#> Current smoker │ <.001 .14
#> No │ 77.2
#> Yes │ 20.8
#> (Missing) │ 2.1
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Physical activity │ <.001 .21
#> No │ 54.2
#> Yes │ 45.8
# Survey weights with rescaling.
table_categorical(
sochealth,
select = c(smoking, physical_activity),
by = education,
weights = "weight",
rescale = TRUE
)
#> Categorical table by education
#>
#> Variable │ Lower secondary n Lower secondary %
#> ───────────────────────────┼──────────────────────────────────────
#> Current smoker │
#> No │ 176 68.1
#> Yes │ 79 30.6
#> (Missing) │ 4 1.4
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Regular physical activity │
#> No │ 174 67.2
#> Yes │ 85 32.8
#>
#> Variable │ Upper secondary n Upper secondary % Tertiary n
#> ───────────────────────────┼──────────────────────────────────────────────────
#> Current smoker │
#> No │ 419 76.6 325
#> Yes │ 114 21.0 60
#> (Missing) │ 13 2.4 10
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Regular physical activity │
#> No │ 315 57.7 166
#> Yes │ 231 42.3 229
#>
#> Variable │ Tertiary % Total n Total % p Cramer's V
#> ───────────────────────────┼─────────────────────────────────────────────────
#> Current smoker │ <.001 .13
#> No │ 82.2 919 76.6
#> Yes │ 15.2 254 21.1
#> (Missing) │ 2.6 27 2.2
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Regular physical activity │ <.001 .19
#> No │ 41.9 655 54.6
#> Yes │ 58.1 545 45.4
# Confidence interval for the association measure.
table_categorical(
sochealth,
select = smoking,
by = education,
assoc_ci = TRUE
)
#> Categorical table by education
#>
#> Variable │ Lower secondary n Lower secondary % Upper secondary n
#> ────────────────┼─────────────────────────────────────────────────────────
#> Current smoker │
#> No │ 179 68.6 415
#> Yes │ 78 29.9 112
#> (Missing) │ 4 1.5 12
#>
#> Variable │ Upper secondary % Tertiary n Tertiary % Total n Total %
#> ────────────────┼─────────────────────────────────────────────────────────────
#> Current smoker │
#> No │ 77.0 332 83.0 926 77.2
#> Yes │ 20.8 59 14.8 249 20.8
#> (Missing) │ 2.2 9 2.2 25 2.1
#>
#> Variable │ p Cramer's V CI lower CI upper
#> ────────────────┼───────────────────────────────────────
#> Current smoker │ <.001 .14 .08 .19
#> No │
#> Yes │
#> (Missing) │
# --- Per-variable association measure ----------------------------------
# Default (`assoc_measure = "auto"`): one measure per row variable based on
# the variable type (2x2 -> Phi, both ordered factors -> Kendall's Tau-b,
# otherwise Cramer's V). When the chosen measures differ across rows, the
# column header collapses to `"Effect size"` and an APA-style `Note.` line
# documents which measure was used for which variable.
table_categorical(
sochealth,
select = c(smoking, education),
by = sex
)
#> Categorical table by sex
#>
#> Variable │ Female n Female % Male n Male % Total n Total %
#> ─────────────────────────┼──────────────────────────────────────────────────────
#> Current smoker │
#> No │ 475 76.6 451 77.8 926 77.2
#> Yes │ 131 21.1 118 20.3 249 20.8
#> (Missing) │ 14 2.3 11 1.9 25 2.1
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Highest education level │
#> Lower secondary │ 134 21.6 127 21.9 261 21.8
#> Upper secondary │ 290 46.8 249 42.9 539 44.9
#> Tertiary │ 196 31.6 204 35.2 400 33.3
#>
#> Variable │ p Effect size
#> ─────────────────────────┼───────────────────
#> Current smoker │ .713 .01
#> No │
#> Yes │
#> (Missing) │
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Highest education level │ .344 .04
#> Lower secondary │
#> Upper secondary │
#> Tertiary │
#>
#> Note. Phi: Current smoker; Cramer's V: Highest education level.
# Force a uniform measure across all row variables.
table_categorical(
sochealth,
select = c(smoking, education),
by = sex,
assoc_measure = "cramer_v"
)
#> Categorical table by sex
#>
#> Variable │ Female n Female % Male n Male % Total n Total %
#> ─────────────────────────┼──────────────────────────────────────────────────────
#> Current smoker │
#> No │ 475 76.6 451 77.8 926 77.2
#> Yes │ 131 21.1 118 20.3 249 20.8
#> (Missing) │ 14 2.3 11 1.9 25 2.1
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Highest education level │
#> Lower secondary │ 134 21.6 127 21.9 261 21.8
#> Upper secondary │ 290 46.8 249 42.9 539 44.9
#> Tertiary │ 196 31.6 204 35.2 400 33.3
#>
#> Variable │ p Cramer's V
#> ─────────────────────────┼──────────────────
#> Current smoker │ .713 .01
#> No │
#> Yes │
#> (Missing) │
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Highest education level │ .344 .04
#> Lower secondary │
#> Upper secondary │
#> Tertiary │
# Per-variable override (recommended named form).
table_categorical(
sochealth,
select = c(smoking, education, self_rated_health),
by = sex,
assoc_measure = c(
smoking = "phi", # binary x binary
education = "cramer_v", # multi-category nominal
self_rated_health = "tau_b" # ordinal x binary, Tau-b
)
)
#> Categorical table by sex
#>
#> Variable │ Female n Female % Male n Male % Total n Total %
#> ─────────────────────────┼──────────────────────────────────────────────────────
#> Current smoker │
#> No │ 475 76.6 451 77.8 926 77.2
#> Yes │ 131 21.1 118 20.3 249 20.8
#> (Missing) │ 14 2.3 11 1.9 25 2.1
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Highest education level │
#> Lower secondary │ 134 21.6 127 21.9 261 21.8
#> Upper secondary │ 290 46.8 249 42.9 539 44.9
#> Tertiary │ 196 31.6 204 35.2 400 33.3
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Self-rated health │
#> (Missing) │ 10 1.6 10 1.7 20 1.7
#> Poor │ 31 5.0 30 5.2 61 5.1
#> Fair │ 143 23.1 123 21.2 266 22.2
#> Good │ 282 45.5 276 47.6 558 46.5
#> Very good │ 154 24.8 141 24.3 295 24.6
#>
#> Variable │ p Effect size
#> ─────────────────────────┼───────────────────
#> Current smoker │ .713 .01
#> No │
#> Yes │
#> (Missing) │
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Highest education level │ .344 .04
#> Lower secondary │
#> Upper secondary │
#> Tertiary │
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#> Self-rated health │ .849 .01
#> (Missing) │
#> Poor │
#> Fair │
#> Good │
#> Very good │
#>
#> Note. Phi: Current smoker; Cramer's V: Highest education level; Kendall's Tau-b: Self-rated health.
# --- Output formats -----------------------------------------------------
# The rendered outputs below all wrap the same call:
# table_categorical(sochealth,
# select = c(smoking, physical_activity),
# by = sex)
# only `output` changes. Assign each result to a variable -- some
# engines auto-print as a console-friendly text fallback inside
# the `?` help viewer.
# Wide data.frame (one row per modality).
table_categorical(
sochealth,
select = c(smoking, physical_activity),
by = sex,
output = "data.frame"
)
#> Variable Level Female n Female % Male n Male %
#> 1 Current smoker No 475 76.612903 451 77.758621
#> 2 Current smoker Yes 131 21.129032 118 20.344828
#> 3 Current smoker (Missing) 14 2.258065 11 1.896552
#> 4 Regular physical activity No 334 53.870968 316 54.482759
#> 5 Regular physical activity Yes 286 46.129032 264 45.517241
#> Total n Total % Chi2 df p Phi
#> 1 926 77.166667 0.1357733 1 0.7125196 0.010749501
#> 2 249 20.750000 0.1357733 1 0.7125196 0.010749501
#> 3 25 2.083333 0.1357733 1 0.7125196 0.010749501
#> 4 650 54.166667 0.0451784 1 0.8316763 0.006135851
#> 5 550 45.833333 0.0451784 1 0.8316763 0.006135851
# Long data.frame (one row per (modality x group)).
table_categorical(
sochealth,
select = c(smoking, physical_activity),
by = sex,
output = "long"
)
#> variable level group n pct chi2 df
#> 1 Current smoker No Female 475 76.612903 0.1357733 1
#> 2 Current smoker No Male 451 77.758621 0.1357733 1
#> 3 Current smoker No Total 926 77.166667 0.1357733 1
#> 4 Current smoker Yes Female 131 21.129032 0.1357733 1
#> 5 Current smoker Yes Male 118 20.344828 0.1357733 1
#> 6 Current smoker Yes Total 249 20.750000 0.1357733 1
#> 7 Current smoker (Missing) Female 14 2.258065 0.1357733 1
#> 8 Current smoker (Missing) Male 11 1.896552 0.1357733 1
#> 9 Current smoker (Missing) Total 25 2.083333 0.1357733 1
#> 10 Regular physical activity No Female 334 53.870968 0.0451784 1
#> 11 Regular physical activity No Male 316 54.482759 0.0451784 1
#> 12 Regular physical activity No Total 650 54.166667 0.0451784 1
#> 13 Regular physical activity Yes Female 286 46.129032 0.0451784 1
#> 14 Regular physical activity Yes Male 264 45.517241 0.0451784 1
#> 15 Regular physical activity Yes Total 550 45.833333 0.0451784 1
#> p Phi
#> 1 0.7125196 0.010749501
#> 2 0.7125196 0.010749501
#> 3 0.7125196 0.010749501
#> 4 0.7125196 0.010749501
#> 5 0.7125196 0.010749501
#> 6 0.7125196 0.010749501
#> 7 0.7125196 0.010749501
#> 8 0.7125196 0.010749501
#> 9 0.7125196 0.010749501
#> 10 0.8316763 0.006135851
#> 11 0.8316763 0.006135851
#> 12 0.8316763 0.006135851
#> 13 0.8316763 0.006135851
#> 14 0.8316763 0.006135851
#> 15 0.8316763 0.006135851
# \donttest{
# Rendered HTML / docx objects -- best viewed inside a
# Quarto / R Markdown document or a pkgdown article.
if (requireNamespace("tinytable", quietly = TRUE)) {
tt <- table_categorical(
sochealth, select = c(smoking, physical_activity), by = sex,
output = "tinytable"
)
}
if (requireNamespace("gt", quietly = TRUE)) {
tbl <- table_categorical(
sochealth, select = c(smoking, physical_activity), by = sex,
output = "gt"
)
}
if (requireNamespace("flextable", quietly = TRUE)) {
ft <- table_categorical(
sochealth, select = c(smoking, physical_activity), by = sex,
output = "flextable"
)
}
# Excel and Word: write to a temporary file.
if (requireNamespace("openxlsx2", quietly = TRUE)) {
tmp <- tempfile(fileext = ".xlsx")
table_categorical(
sochealth, select = c(smoking, physical_activity), by = sex,
output = "excel", excel_path = tmp
)
unlink(tmp)
}
if (
requireNamespace("flextable", quietly = TRUE) &&
requireNamespace("officer", quietly = TRUE)
) {
tmp <- tempfile(fileext = ".docx")
table_categorical(
sochealth, select = c(smoking, physical_activity), by = sex,
output = "word", word_path = tmp
)
unlink(tmp)
}
# }
if (FALSE) { # \dontrun{
# Clipboard: writes to the system clipboard.
table_categorical(
sochealth, select = c(smoking, physical_activity), by = sex,
output = "clipboard"
)
} # }