---
title: "Knowledge, Attitudes, and Perceived Barriers Toward Pediatric Preventive Dentistry"
subtitle: "Demetrio Data"
date: today
format:
html:
toc: true
toc-depth: 3
number-sections: true
theme: cosmo
code-fold: true
code-tools: true
fig-width: 9
fig-height: 5
fig-dpi: 300
execute:
warning: false
message: false
---
# Setup
## Load packages
```{r}
#| label: setup
# Load all required packages via pacman
if (!requireNamespace("pacman", quietly = TRUE)) install.packages("pacman")
pacman::p_load(tidyverse, here, janitor, viridis, scales, MASS, gtsummary)
```
## Read and clean data
```{r}
#| label: data-import
# Read the raw CSV, normalize column names with janitor, then rename
# to short workable aliases. This is the only persistent object we keep
# thorughout the analysis
df <- read_csv(here("data", "data.csv"),
show_col_types = FALSE) |>
clean_names() |>
# Rename the long janitor names to short aliases
rename(
specialty = dental_specialty,
q1_sugar = x1_what_is_the_maximum_recommended_sugar_consumption_during_the_day,
q2_first_visit = x2_at_what_age_is_the_first_visit_recommended,
q3_fluoride = x3_which_of_the_following_statements_about_fluoride_is_correct,
q4_sealants = x4_which_of_the_following_questions_about_sealants_is_correct,
q5_ecc = x5_which_of_the_following_statements_about_early_childhood_caries_ecc_is_correct,
q6_brushing = x6_which_of_the_following_statements_about_brushing_is_correct,
q7_risk = x7_which_of_the_following_statements_about_oral_health_risk_factors_is_wrong,
q8_smoking = x8_dentists_should_carry_out_preventive_activities_for_smoking_cessation,
q9_paed_prev = x9_dentists_should_carry_out_preventive_activities_in_paediatric_dentistry,
q10_equipped = x10_dentists_are_well_equipped_in_carrying_out_preventive_care_in_paediatric_dentistry,
q11_sealants = x11_when_needed_do_you_apply_dental_sealants,
q12_varnish = x12_when_needed_do_you_apply_fluoride_varnish,
q13_ohi = x13_when_needed_do_you_give_oral_hygiene_instructions,
q14_diet = x14_when_needed_do_you_provide_any_dietary_advice,
q15_time = x15_lack_of_time,
q16_remuneration = x16_lack_of_remuneration,
q17_motivation = x17_lack_of_motivation_in_implementing_preventive_care,
q18_compliance = x18_poor_patient_compliance,
q19_knowledge_b = x19_lack_of_knowledge,
q20_training = x20_lack_of_training
) |>
# Recode categorical variables
mutate(
age_group = factor(age,
levels = 1:6,
labels = c("25-34", "35-44", "45-54",
"55-64", "65-74", "75+")),
gender_label = factor(gender,
levels = c(0, 1),
labels = c("Male", "Female")),
specialty_label = factor(specialty,
levels = 1:7,
labels = c("General Dentistry", "Pediatric Dentistry",
"Orthodontics", "Oral Surgery",
"Restorative/Endo", "Prosthodontics",
"Periodontics")),
country = factor(country)
) -> df
```
# Demographics
## Demographics table (Table 1)
```{r}
#| label: table1-demographics
# Table 1: sample characteristics stratified by country using gtsummary
df |>
select(country, age_group, gender_label, specialty_label) |>
tbl_summary(
by = country,
label = list(
age_group ~ "Age group",
gender_label ~ "Gender",
specialty_label ~ "Dental specialty"
),
missing = "ifany",
missing_text = "Missing"
) |>
add_overall() |>
add_p(test = list(all_categorical() ~ "chisq.test")) |>
modify_header(label ~ "**Characteristic**") |>
bold_labels()
```
# Knowledge
## Descriptives by country
```{r}
#| label: knowledge-descriptives
# Knowledge score summary stratified by country
df |>
select(country, score_knowledge) |>
tbl_summary(
by = country,
label = list(score_knowledge ~ "Knowledge score (0-7)"),
statistic = list(all_continuous() ~ "{mean} ({sd}) | {median} [{p25}, {p75}]"),
missing = "no"
) |>
add_overall() |>
add_p(test = list(all_continuous() ~ "kruskal.test")) |>
bold_labels()
```
## Item-level correct response rate
```{r}
#| label: knowledge-items
# Proportion correct for each knowledge item, stratified by country
df |>
select(country, q1_sugar:q7_risk) |>
# Convert to factors so gtsummary shows proportions
mutate(across(q1_sugar:q7_risk, ~ factor(.x, levels = c(1, 0),
labels = c("Correct", "Incorrect")))) |>
tbl_summary(
by = country,
label = list(
q1_sugar ~ "Sugar intake",
q2_first_visit ~ "First visit age",
q3_fluoride ~ "Fluoride",
q4_sealants ~ "Sealants",
q5_ecc ~ "ECC",
q6_brushing ~ "Brushing",
q7_risk ~ "Risk factors"
),
value = list(q1_sugar ~ "Correct", q2_first_visit ~ "Correct",
q3_fluoride ~ "Correct", q4_sealants ~ "Correct",
q5_ecc ~ "Correct", q6_brushing ~ "Correct",
q7_risk ~ "Correct"),
missing = "no"
) |>
add_overall() |>
add_p(test = list(all_categorical() ~ "chisq.test")) |>
bold_labels()
```
## Knowledge by specialty
```{r}
#| label: knowledge-specialty
# Knowledge score stratified by specialty
df |>
select(country, age_group, gender_label, specialty_label) |>
tbl_summary(
by = country,
label = list(
age_group ~ "Age group",
gender_label ~ "Gender",
specialty_label ~ "Dental specialty"
),
missing = "ifany",
missing_text = "Missing"
) |>
add_overall() |>
add_p(test = list(all_categorical() ~ "chisq.test.no.correct"),
test.args = all_tests("chisq.test.no.correct") ~
list(simulate.p.value = TRUE, B = 2000)) |>
modify_header(label ~ "**Characteristic**") |>
bold_labels()
```
## Kruskal-Wallis: knowledge by country
```{r}
#| label: kw-knowledge-country
# Non-parametric comparison given ordinal nature of the score
kruskal.test(score_knowledge ~ country, data = df)
```
## Kruskal-Wallis: knowledge by specialty
```{r}
#| label: kw-knowledge-specialty
# Compare knowledge scores accross specialties
kruskal.test(score_knowledge ~ specialty_label, data = df)
```
## Knowledge by gender
```{r}
#| label: knowledge-gender
# Knowledge score comparison by gender
df |>
filter(!is.na(gender_label)) |>
select(gender_label, score_knowledge) |>
tbl_summary(
by = gender_label,
label = list(score_knowledge ~ "Knowledge score (0-7)"),
statistic = list(all_continuous() ~ "{mean} ({sd}) | {median} [{p25}, {p75}]"),
missing = "no"
) |>
bold_labels()
```
# Attitudes
Likert scale: 1 = Strongly agree, 2 = Agree, 3 = Disagree, 4 = Strongly disagree.
## Attitude items by country
```{r}
#| label: attitudes-table
# Attitude items as ordered factors, stratified by country
df |>
select(country, q8_smoking, q9_paed_prev, q10_equipped) |>
mutate(across(q8_smoking:q10_equipped,
~ factor(.x, levels = 1:4,
labels = c("Strongly agree", "Agree",
"Disagree", "Strongly disagree")))) |>
tbl_summary(
by = country,
label = list(
q8_smoking ~ "Preventive activities: smoking cessation",
q9_paed_prev ~ "Preventive activities: paediatric dentistry",
q10_equipped ~ "Well equipped for preventive care"
),
missing = "no"
) |>
add_overall() |>
add_p(test = list(all_categorical() ~ "chisq.test")) |>
bold_labels()
```
# Practice
Likert scale: 1 = Always, 2 = Often, 3 = Sometimes, 4 = Never.
## Practice items by country
```{r}
#| label: practice-table
# Practice items as ordered factors, stratified by country
df |>
select(country, q11_sealants:q14_diet) |>
mutate(across(q11_sealants:q14_diet,
~ factor(.x, levels = 1:4,
labels = c("Always", "Often",
"Sometimes", "Never")))) |>
tbl_summary(
by = country,
label = list(
q11_sealants ~ "Apply dental sealants",
q12_varnish ~ "Apply fluoride varnish",
q13_ohi ~ "Give oral hygiene instructions",
q14_diet ~ "Provide dietary advice"
),
missing = "no"
) |>
add_overall() |>
add_p(test = list(all_categorical() ~ "chisq.test")) |>
bold_labels()
```
## Practice by age group
```{r}
#| label: practice-age
# Practice items stratified by age group
df |>
select(age_group, q11_sealants:q14_diet) |>
mutate(across(q11_sealants:q14_diet,
~ factor(.x, levels = 1:4,
labels = c("Always", "Often",
"Sometimes", "Never")))) |>
tbl_summary(
by = age_group,
label = list(
q11_sealants ~ "Apply dental sealants",
q12_varnish ~ "Apply fluoride varnish",
q13_ohi ~ "Give oral hygiene instructions",
q14_diet ~ "Provide dietary advice"
),
missing = "no"
) |>
add_p(test = list(all_categorical() ~ "chisq.test")) |>
bold_labels()
```
# Barriers
Likert scale: 1 = Strongly disagree, 2 = Disagree, 3 = Agree, 4 = Strongly agree.
## Barrier items by country
```{r}
#| label: barriers-country-table
# Barrier items as ordered factors, stratified by country
# Includes overall column and chi-squared p-values
df |>
select(country, q15_time:q20_training) |>
mutate(across(q15_time:q20_training,
~ factor(.x, levels = 1:4,
labels = c("Strongly disagree", "Disagree",
"Agree", "Strongly agree")))) |>
tbl_summary(
by = country,
label = list(
q15_time ~ "Lack of time",
q16_remuneration ~ "Lack of remuneration",
q17_motivation ~ "Lack of motivation",
q18_compliance ~ "Poor patient compliance",
q19_knowledge_b ~ "Lack of knowledge",
q20_training ~ "Lack of training"
),
missing = "no"
) |>
add_overall() |>
add_p(test = list(all_categorical() ~ "chisq.test")) |>
bold_labels()
```
## Barrier items by specialty
```{r}
#| label: barriers-specialty-table
# Barriers stratified by speciaty
df |>
select(specialty_label, q15_time:q20_training) |>
mutate(across(q15_time:q20_training,
~ factor(.x, levels = 1:4,
labels = c("Strongly disagree", "Disagree",
"Agree", "Strongly agree")))) |>
tbl_summary(
by = specialty_label,
label = list(
q15_time ~ "Lack of time",
q16_remuneration ~ "Lack of remuneration",
q17_motivation ~ "Lack of motivation",
q18_compliance ~ "Poor patient compliance",
q19_knowledge_b ~ "Lack of knowledge",
q20_training ~ "Lack of training"
),
missing = "no"
) |>
add_p(test = list(all_categorical() ~ "chisq.test")) |>
bold_labels()
```
# Visualizations
## Knowledge score by country
```{r}
#| label: fig-knowledge-country
#| fig-cap: "Knowledge score distribution by country"
# Boxplot ordered by median knowledge score
df |>
ggplot(aes(x = fct_reorder(country, score_knowledge, .fun = median),
y = score_knowledge, fill = country)) +
geom_boxplot(alpha = 0.8, show.legend = FALSE) +
geom_jitter(alpha = 0.05, width = 0.2) +
scale_fill_viridis_d() +
labs(x = "Country", y = "Knowledge Score (0-7)") +
coord_flip() +
theme_minimal(base_size = 13) +
theme(legend.position = "none")
ggsave(here("output", "fig1_knowledge_by_country.png"),
width = 8, height = 5, dpi = 300)
```
## Knowledge item heatmap
```{r}
#| label: fig-knowledge-heatmap
#| fig-cap: "Correct response rate by knowledge item and country"
# Heatmap of item-level performace across countries
df |>
select(country, q1_sugar:q7_risk) |>
pivot_longer(cols = q1_sugar:q7_risk,
names_to = "item",
values_to = "correct") |>
mutate(
item = case_when(
item == "q1_sugar" ~ "Sugar intake",
item == "q2_first_visit" ~ "First visit age",
item == "q3_fluoride" ~ "Fluoride",
item == "q4_sealants" ~ "Sealants",
item == "q5_ecc" ~ "ECC",
item == "q6_brushing" ~ "Brushing",
item == "q7_risk" ~ "Risk factors"
)
) |>
group_by(country, item) |>
summarise(pct_correct = mean(correct, na.rm = TRUE) * 100,
.groups = "drop") |>
ggplot(aes(x = item, y = country, fill = pct_correct)) +
geom_tile(color = "white", linewidth = 0.5) +
geom_text(aes(label = sprintf("%.0f%%", pct_correct)), size = 3) +
scale_fill_viridis_c(name = "% Correct", limits = c(0, 100)) +
labs(x = NULL, y = NULL) +
theme_minimal(base_size = 12) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
ggsave(here("output", "fig2_knowledge_heatmap.png"),
width = 9, height = 5, dpi = 300)
```
## Knowledge by specialty
```{r}
#| label: fig-knowledge-specialty
#| fig-cap: "Knowledge score distribution by dental specialty"
# Violin + boxplot combination for specialty comparisons
df |>
ggplot(aes(x = fct_reorder(specialty_label, score_knowledge, .fun = median),
y = score_knowledge, fill = specialty_label)) +
geom_violin(alpha = 0.5, show.legend = FALSE) +
geom_boxplot(width = 0.15, alpha = 0.8, show.legend = FALSE) +
scale_fill_viridis_d() +
labs(x = "Specialty", y = "Knowledge Score (0-7)") +
coord_flip() +
theme_minimal(base_size = 13) +
ggtitle("Knowledge score distribution by dental specialty")
ggsave(here("output", "fig6_knowledge_by_specialty.png"),
width = 9, height = 5, dpi = 300)
```
```{r}
df |>
ggplot(aes(x = fct_reorder(specialty_label, score_knowledge, .fun = median),
y = score_knowledge, fill = specialty_label)) +
geom_violin(alpha = 0.5, show.legend = FALSE) +
geom_boxplot(width = 0.15, alpha = 0.8, show.legend = FALSE) +
scale_fill_viridis_d() +
labs(x = "Specialty", y = "Knowledge Score (0-7)") +
coord_flip() +
theme_minimal(base_size = 13) +
facet_grid( . ~ country) +
ggtitle("Knowledge score distribution by dental specialty and country")
ggsave(here("output", "fig6_1_knowledge_by_specialty_by_country.png"),
width = 9, height = 5, dpi = 300)
```
## Barriers: stacked bar chart
```{r}
#| label: fig-barriers-stacked
#| fig-cap: "Perceived barriers to preventive dentistry (overall)"
# Stacked bar chart for barrier Likert responses
df |>
select(q15_time:q20_training) |>
pivot_longer(cols = everything(),
names_to = "barrier",
values_to = "response") |>
filter(!is.na(response)) |>
mutate(
response_label = factor(response,
levels = 1:4,
labels = c("Strongly disagree", "Disagree",
"Agree", "Strongly agree")),
barrier = case_when(
barrier == "q15_time" ~ "Lack of time",
barrier == "q16_remuneration" ~ "Lack of remuneration",
barrier == "q17_motivation" ~ "Lack of motivation",
barrier == "q18_compliance" ~ "Poor compliance",
barrier == "q19_knowledge_b" ~ "Lack of knowledge",
barrier == "q20_training" ~ "Lack of training"
)
) |>
count(barrier, response_label) |>
group_by(barrier) |>
mutate(pct = n / sum(n) * 100) |>
ungroup() |>
ggplot(aes(x = fct_rev(barrier), y = pct, fill = response_label)) +
geom_col(position = "stack", width = 0.7) +
scale_fill_viridis_d(name = "Response", option = "D") +
labs(x = NULL, y = "Percentage (%)") +
coord_flip() +
theme_minimal(base_size = 13) +
theme(legend.position = "top") +
ggtitle("Perceived barriers to preventive dentistry (overall)")
ggsave(here("output", "fig3_barriers_stacked.png"),
width = 9, height = 5, dpi = 300)
```
## Barriers heatmap by country
```{r}
#| label: fig-barriers-heatmap
#| fig-cap: "Perceived barriers by country (% Agree or Strongly Agree)"
# Heatmap showing barrier agreement rates across countries
df |>
select(country, q15_time:q20_training) |>
pivot_longer(cols = q15_time:q20_training,
names_to = "barrier",
values_to = "response") |>
filter(!is.na(response)) |>
mutate(
agree = if_else(response >= 3, 1, 0),
barrier = case_when(
barrier == "q15_time" ~ "Time",
barrier == "q16_remuneration" ~ "Remuneration",
barrier == "q17_motivation" ~ "Motivation",
barrier == "q18_compliance" ~ "Patient compliance",
barrier == "q19_knowledge_b" ~ "Knowledge",
barrier == "q20_training" ~ "Training"
)
) |>
group_by(country, barrier) |>
summarise(pct_agree = mean(agree) * 100, .groups = "drop") |>
ggplot(aes(x = barrier, y = country, fill = pct_agree)) +
geom_tile(color = "white", linewidth = 0.5) +
geom_text(aes(label = sprintf("%.0f%%", pct_agree)), size = 3) +
scale_fill_viridis_c(name = "% Agree", option = "D") +
labs(x = NULL, y = NULL) +
theme_minimal(base_size = 12) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
ggtitle("Perceived barriers by country (% Agree or Strongly Agree)")
ggsave(here("output", "fig5_barriers_heatmap.png"),
width = 9, height = 5, dpi = 300)
```
## Practice frequency by country
```{r}
#| label: fig-practice-country
#| fig-cap: "Preventive practice frequency by country (% Always or Often)"
# Grouped bar chart for practice items across countries
df |>
select(country, q11_sealants:q14_diet) |>
pivot_longer(cols = q11_sealants:q14_diet,
names_to = "practice",
values_to = "response") |>
filter(!is.na(response)) |>
mutate(
frequent = if_else(response <= 2, 1, 0),
practice = case_when(
practice == "q11_sealants" ~ "Sealants",
practice == "q12_varnish" ~ "Fluoride varnish",
practice == "q13_ohi" ~ "OHI",
practice == "q14_diet" ~ "Dietary advice"
)
) |>
group_by(country, practice) |>
summarise(pct = mean(frequent) * 100, .groups = "drop") |>
ggplot(aes(x = country, y = pct, fill = practice)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
scale_fill_viridis_d(name = "Practice", option = "D") +
labs(x = NULL, y = "% Always or Often") +
theme_minimal(base_size = 12) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
coord_flip() +
ggtitle("Preventive practice frequency by country (% Always or Often)")
ggsave(here("output", "fig4_practice_by_country.png"),
width = 10, height = 5, dpi = 300)
```
## Overall ranking of preventive practices
```{r}
#| label: fig-practice-ranking-overall
#| fig-cap: "Overall ranking of preventive practices (% Always or Often)"
# Proportion reporting Always/Often for each practice item, overall
df |>
select(q11_sealants:q14_diet) |>
pivot_longer(cols = everything(),
names_to = "practice",
values_to = "response") |>
filter(!is.na(response)) |>
mutate(
frequent = if_else(response <= 2, 1, 0),
practice = case_when(
practice == "q11_sealants" ~ "Sealants",
practice == "q12_varnish" ~ "Fluoride varnish",
practice == "q13_ohi" ~ "Oral hygiene instructions",
practice == "q14_diet" ~ "Dietary advice"
)
) |>
group_by(practice) |>
summarise(pct = mean(frequent) * 100, .groups = "drop") |>
ggplot(aes(x = fct_reorder(practice, pct), y = pct, fill = pct)) +
geom_col(width = 0.6) +
geom_text(aes(label = sprintf("%.1f%%", pct)), hjust = -0.1, size = 4) +
scale_fill_viridis_c(option = "D", guide = "none") +
labs(x = NULL, y = "% Always or Often") +
coord_flip(ylim = c(0, 100)) +
theme_minimal(base_size = 13) +
ggtitle("Overall ranking of preventive practices (% Always or Often)")
ggsave(here("output", "fig7_practice_ranking_overall.png"),
width = 8, height = 4, dpi = 300)
```
## Overall ranking of preventive practices by country
```{r}
#| label: fig-practice-ranking-country
#| fig-cap: "Ranking of preventive practices by country (% Always or Often)"
# Practice ranking faceted by country
df |>
select(country, q11_sealants:q14_diet) |>
pivot_longer(cols = q11_sealants:q14_diet,
names_to = "practice",
values_to = "response") |>
filter(!is.na(response)) |>
mutate(
frequent = if_else(response <= 2, 1, 0),
practice = case_when(
practice == "q11_sealants" ~ "Sealants",
practice == "q12_varnish" ~ "Fluoride varnish",
practice == "q13_ohi" ~ "OHI",
practice == "q14_diet" ~ "Dietary advice"
)
) |>
group_by(country, practice) |>
summarise(pct = mean(frequent) * 100, .groups = "drop") |>
ggplot(aes(x = fct_reorder(practice, pct), y = pct, fill = practice)) +
geom_col(width = 0.7) +
geom_text(aes(label = sprintf("%.0f%%", pct)), hjust = -0.1, size = 2.5) +
scale_fill_viridis_d(option = "C", guide = "none") +
labs(x = NULL, y = "% Always or Often") +
coord_flip(ylim = c(0, 105)) +
facet_wrap(~ country, ncol = 4) +
theme_minimal(base_size = 11) +
theme(strip.text = element_text(face = "bold")) +
ggtitle("Ranking of preventive practices by country (% Always or Often)")
ggsave(here("output", "fig8_practice_ranking_by_country.png"),
width = 12, height = 6, dpi = 300)
```
## Distribution of preventive practice score
```{r}
#| label: fig-practice-score-histogram
#| fig-cap: "Distribution of composite preventive practice score"
# Composite score: sum of all 4 practice items (range 4-16)
# Lower score = check"more frequent preventive practice?
df |>
mutate(
practice_score = q11_sealants + q12_varnish + q13_ohi + q14_diet
) |>
filter(!is.na(practice_score)) |>
ggplot(aes(x = practice_score)) +
geom_histogram(binwidth = 1, color = "white", linewidth = 0.3) +
geom_vline(aes(xintercept = mean(practice_score, na.rm = TRUE)),
linetype = "dashed", color = "red", linewidth = 0.8) +
# scale_fill_viridis_c(option = "D", guide = "none") +
scale_x_continuous(breaks = 0:16) +
labs(
title = "Distribution of composite preventive practice score",
x = "Preventive Practice Score (0 = best, 16 = worst)",
y = "Frequency"
) +
annotate("text", x = 14, y = Inf, vjust = 2, hjust = 1, size = 3.5,
label = "Dashed line = mean") +
theme_minimal(base_size = 13)
ggsave(here("output", "fig9_practice_score_histogram.png"),
width = 8, height = 5, dpi = 300)
```
# Summary table
```{r}
#| label: summary-table
# Recode practice and barrier items into binary for a sake of clarity
df |>
transmute(
country,
score_knowledge,
# Practice: binary always/often
sealants_frequent = if_else(q11_sealants <= 2, 1L, 0L),
varnish_frequent = if_else(q12_varnish <= 2, 1L, 0L),
ohi_frequent = if_else(q13_ohi <= 2, 1L, 0L),
diet_frequent = if_else(q14_diet <= 2, 1L, 0L),
# Barriers: binary agree/strongly agree
barrier_time = if_else(q15_time >= 3, 1L, 0L),
barrier_remuneration = if_else(q16_remuneration >= 3, 1L, 0L),
barrier_motivation = if_else(q17_motivation >= 3, 1L, 0L),
barrier_compliance = if_else(q18_compliance >= 3, 1L, 0L),
barrier_knowledge = if_else(q19_knowledge_b >= 3, 1L, 0L),
barrier_training = if_else(q20_training >= 3, 1L, 0L)
) |>
tbl_summary(
by = country,
label = list(
score_knowledge ~ "Knowledge score (0-7)",
sealants_frequent ~ "Sealants (Always/Often)",
varnish_frequent ~ "Fluoride varnish (Always/Often)",
ohi_frequent ~ "OHI (Always/Often)",
diet_frequent ~ "Dietary advice (Always/Often)",
barrier_time ~ "Barrier: lack of time",
barrier_remuneration ~ "Barrier: lack of remuneration",
barrier_motivation ~ "Barrier: lack of motivation",
barrier_compliance ~ "Barrier: poor compliance",
barrier_knowledge ~ "Barrier: lack of knowledge",
barrier_training ~ "Barrier: lack of training"
),
statistic = list(
all_continuous() ~ "{mean} ({sd})",
all_categorical() ~ "{p}%"
),
missing = "no"
) |>
add_overall() |>
bold_labels()
```