Tutorial completo com o pacote gtsummary
Esta aula foi construída para que você produza tabelas prontas para relatórios, artigos e apresentações com poucas linhas de código. Os dados usados são o conjunto
CO2, disponível no R base. Todo o código está funcional e pronto para reproduzir.
Inscreva-se já no canal Link.
gtsummary e quando usá-lotbl_summary()add_p() e add_difference()tbl_regression()tbl_merge() e tbl_stack()gtsummary foi criado por Daniel D. Sjoberg e colaboradores. Produz tabelas descritivas e de resultados de modelos prontas para publicação.
{gt}, {broom} e {labelled}CO2 está disponível no R base. Registra um experimento de absorção de CO2 em plantas de capim-bermuda submetidas a diferentes tratamentos e concentrações de dióxido de carbono.Rows: 84
Columns: 5
$ Plant <ord> Qn1, Qn1, Qn1, Qn1, Qn1, Qn1, Qn1, Qn2, Qn2, Qn2, Qn2, Qn2, …
$ Type <fct> Quebec, Quebec, Quebec, Quebec, Quebec, Quebec, Quebec, Queb…
$ Treatment <fct> nonchilled, nonchilled, nonchilled, nonchilled, nonchilled, …
$ conc <dbl> 95, 175, 250, 350, 500, 675, 1000, 95, 175, 250, 350, 500, 6…
$ uptake <dbl> 16.0, 30.4, 34.8, 37.2, 35.3, 39.2, 39.7, 13.6, 27.3, 37.1, …
Plant Type Treatment conc uptake
1 Qn1 Quebec nonchilled 95 16.0
2 Qn1 Quebec nonchilled 175 30.4
3 Qn1 Quebec nonchilled 250 34.8
4 Qn1 Quebec nonchilled 350 37.2
5 Qn1 Quebec nonchilled 500 35.3
6 Qn1 Quebec nonchilled 675 39.2
7 Qn1 Quebec nonchilled 1000 39.7
8 Qn2 Quebec nonchilled 95 13.6
9 Qn2 Quebec nonchilled 175 27.3
10 Qn2 Quebec nonchilled 250 37.1
| Variável | Tipo | Descrição |
|---|---|---|
Plant |
Fator | Identificador da planta (84 observações, 12 plantas) |
Type |
Fator | Origem da planta: Quebec ou Mississippi |
Treatment |
Fator | Tratamento aplicado: nonchilled ou chilled |
conc |
Numérica | Concentração de CO2 no ambiente (mL/L) |
uptake |
Numérica | Absorção de CO2 pela planta (umol/m²/s) |
# Selecionar variáveis de análise e traduzir rótulos
co2 <- CO2 |>
as_tibble() |>
select(Type, Treatment, conc, uptake) |>
mutate(
Type = factor(Type,
levels = c("Quebec", "Mississippi")),
Treatment = factor(Treatment,
levels = c("nonchilled", "chilled"),
labels = c("Sem resfriamento", "Com resfriamento")))| Characteristic | N = 841 |
|---|---|
| Type | |
| Quebec | 42 (50%) |
| Mississippi | 42 (50%) |
| Treatment | |
| Sem resfriamento | 42 (50%) |
| Com resfriamento | 42 (50%) |
| conc | |
| 95 | 12 (14%) |
| 175 | 12 (14%) |
| 250 | 12 (14%) |
| 350 | 12 (14%) |
| 500 | 12 (14%) |
| 675 | 12 (14%) |
| 1000 | 12 (14%) |
| uptake | 28 (18, 37) |
| 1 n (%); Median (Q1, Q3) | |
# statistic: define qual estatística usar por tipo de variável
# digits: controla casas decimais
# missing: "no" remove a linha de missing da tabela
co2 |>
tbl_summary(
statistic = list(
all_continuous() ~ "{mean} ({sd})",
all_categorical() ~ "{n} ({p}%)"),
digits = list(all_continuous() ~ 1),
missing = "no") |>
bold_labels()| Characteristic | N = 841 |
|---|---|
| Type | |
| Quebec | 42 (50%) |
| Mississippi | 42 (50%) |
| Treatment | |
| Sem resfriamento | 42 (50%) |
| Com resfriamento | 42 (50%) |
| conc | |
| 95 | 12 (14%) |
| 175 | 12 (14%) |
| 250 | 12 (14%) |
| 350 | 12 (14%) |
| 500 | 12 (14%) |
| 675 | 12 (14%) |
| 1000 | 12 (14%) |
| uptake | 27.2 (10.8) |
| 1 n (%); Mean (SD) | |
# label: renomeia variáveis na tabela sem alterar o dataset
co2 |>
tbl_summary(
label = list(
Type ~ "Origem",
Treatment ~ "Tratamento",
conc ~ "Concentração de CO2 (mL/L)",
uptake ~ "Absorção de CO2 (umol/m²/s)"),
statistic = list(
all_continuous() ~ "{median} ({p25}, {p75})",
all_categorical() ~ "{n} ({p}%)"),
missing = "no") |>
bold_labels()| Characteristic | N = 841 |
|---|---|
| Origem | |
| Quebec | 42 (50%) |
| Mississippi | 42 (50%) |
| Tratamento | |
| Sem resfriamento | 42 (50%) |
| Com resfriamento | 42 (50%) |
| Concentração de CO2 (mL/L) | |
| 95 | 12 (14%) |
| 175 | 12 (14%) |
| 250 | 12 (14%) |
| 350 | 12 (14%) |
| 500 | 12 (14%) |
| 675 | 12 (14%) |
| 1000 | 12 (14%) |
| Absorção de CO2 (umol/m²/s) | 28 (18, 37) |
| 1 n (%); Median (Q1, Q3) | |
# by: estratifica a tabela por uma variável categórica
# add_n(): adiciona coluna com total de observações não ausentes
# add_p(): realiza teste estatístico e adiciona coluna de p-valor
# add_overall(): adiciona coluna com estatísticas gerais
co2 |>
tbl_summary(
by = Type,
label = list(
Treatment ~ "Tratamento",
conc ~ "Concentração de CO2 (mL/L)",
uptake ~ "Absorção de CO2 (umol/m²/s)"),
statistic = list(
all_continuous() ~ "{median} ({p25}, {p75})",
all_categorical() ~ "{n} ({p}%)"),
missing = "no") |>
add_n() |>
add_p() |>
add_overall() |>
bold_labels() |>
modify_header(label = "**Variável**")| Variável | N | Overall N = 841 |
Quebec N = 421 |
Mississippi N = 421 |
p-value2 |
|---|---|---|---|---|---|
| Tratamento | 84 | >0.9 | |||
| Sem resfriamento | 42 (50%) | 21 (50%) | 21 (50%) | ||
| Com resfriamento | 42 (50%) | 21 (50%) | 21 (50%) | ||
| Concentração de CO2 (mL/L) | 84 | >0.9 | |||
| 95 | 12 (14%) | 6 (14%) | 6 (14%) | ||
| 175 | 12 (14%) | 6 (14%) | 6 (14%) | ||
| 250 | 12 (14%) | 6 (14%) | 6 (14%) | ||
| 350 | 12 (14%) | 6 (14%) | 6 (14%) | ||
| 500 | 12 (14%) | 6 (14%) | 6 (14%) | ||
| 675 | 12 (14%) | 6 (14%) | 6 (14%) | ||
| 1000 | 12 (14%) | 6 (14%) | 6 (14%) | ||
| Absorção de CO2 (umol/m²/s) | 84 | 28 (18, 37) | 37 (30, 40) | 19 (14, 28) | <0.001 |
| 1 n (%); Median (Q1, Q3) | |||||
| 2 Pearson’s Chi-squared test; Wilcoxon rank sum test | |||||
# add_difference(): calcula a diferença entre grupos e seu IC 95%
# Complementa o p-valor com a magnitude da diferença
co2 |>
select(Type, conc, uptake) |>
tbl_summary(
by = Type,
label = list(
conc ~ "Concentração de CO2 (mL/L)",
uptake ~ "Absorção de CO2 (umol/m²/s)"),
statistic = list(
all_continuous() ~ "{mean} ({sd})"),
missing = "no") |>
add_difference() |>
bold_labels()| Characteristic | Quebec N = 421 |
Mississippi N = 421 |
Difference2 | 95% CI2 | p-value2 |
|---|---|---|---|---|---|
| Concentração de CO2 (mL/L) | 0.00 | -0.43, 0.43 | |||
| 95 | 6 (14%) | 6 (14%) | |||
| 175 | 6 (14%) | 6 (14%) | |||
| 250 | 6 (14%) | 6 (14%) | |||
| 350 | 6 (14%) | 6 (14%) | |||
| 500 | 6 (14%) | 6 (14%) | |||
| 675 | 6 (14%) | 6 (14%) | |||
| 1000 | 6 (14%) | 6 (14%) | |||
| Absorção de CO2 (umol/m²/s) | 34 (10) | 21 (8) | 13 | 8.8, 16 | <0.001 |
| 1 n (%); Mean (SD) | |||||
| 2 Standardized Mean Difference; Welch Two Sample t-test | |||||
| Abbreviation: CI = Confidence Interval | |||||
# Modelo: absorção de CO2 explicada por origem, tratamento e concentração
modelo_linear <- lm(
uptake ~ Type + Treatment + conc,
data = co2)
# tbl_regression() detecta automaticamente o tipo de modelo
# e formata coeficientes, IC 95% e p-valores
tbl_regression(
modelo_linear,
label = list(
Type ~ "Origem",
Treatment ~ "Tratamento",
conc ~ "Concentração de CO2 (mL/L)")) |>
bold_labels() |>
bold_p(t = 0.05)| Characteristic | Beta | 95% CI | p-value |
|---|---|---|---|
| Origem | |||
| Quebec | — | — | |
| Mississippi | -13 | -15, -10 | <0.001 |
| Tratamento | |||
| Sem resfriamento | — | — | |
| Com resfriamento | -6.9 | -9.5, -4.2 | <0.001 |
| Concentração de CO2 (mL/L) | 0.02 | 0.01, 0.02 | <0.001 |
| Abbreviation: CI = Confidence Interval | |||
# add_glance_source_note(): adiciona R², AIC e outras métricas do modelo
# no rodapé da tabela
tbl_regression(
modelo_linear,
label = list(
Type ~ "Origem",
Treatment ~ "Tratamento",
conc ~ "Concentração de CO2 (mL/L)")) |>
add_glance_source_note(
label = list(r.squared ~ "R²", p.value ~ "p do modelo"),
include = c(r.squared, AIC, p.value)) |>
bold_labels() |>
bold_p(t = 0.05)| Characteristic | Beta | 95% CI | p-value |
|---|---|---|---|
| Origem | |||
| Quebec | — | — | |
| Mississippi | -13 | -15, -10 | <0.001 |
| Tratamento | |||
| Sem resfriamento | — | — | |
| Com resfriamento | -6.9 | -9.5, -4.2 | <0.001 |
| Concentração de CO2 (mL/L) | 0.02 | 0.01, 0.02 | <0.001 |
| Abbreviation: CI = Confidence Interval | |||
| R² = 0.684; AIC = 551; p do modelo = <0.001 | |||
# Dois modelos: um para Quebec, outro para Mississippi
mod_quebec <- lm(uptake ~ Treatment + conc,
data = filter(co2, Type == "Quebec"))
mod_miss <- lm(uptake ~ Treatment + conc,
data = filter(co2, Type == "Mississippi"))
# tbl_merge() apresenta os dois modelos em colunas separadas
list(
tbl_regression(mod_quebec,
label = list(Treatment ~ "Tratamento",
conc ~ "Concentração (mL/L)")),
tbl_regression(mod_miss,
label = list(Treatment ~ "Tratamento",
conc ~ "Concentração (mL/L)"))) |>
tbl_merge(
tab_spanner = c("**Quebec**", "**Mississippi**")) |>
bold_labels()| Characteristic |
Quebec
|
Mississippi
|
||||
|---|---|---|---|---|---|---|
| Beta | 95% CI | p-value | Beta | 95% CI | p-value | |
| Tratamento | ||||||
| Sem resfriamento | — | — | — | — | ||
| Com resfriamento | -3.6 | -7.8, 0.62 | 0.093 | -10 | -13, -7.2 | <0.001 |
| Concentração (mL/L) | 0.02 | 0.02, 0.03 | <0.001 | 0.01 | 0.01, 0.02 | <0.001 |
| Abbreviation: CI = Confidence Interval | ||||||
library(flextable)
# Criar a tabela
tabela_final <- co2 |>
tbl_summary(
by = Type,
label = list(
Treatment ~ "Tratamento",
conc ~ "Concentração de CO2 (mL/L)",
uptake ~ "Absorção de CO2 (umol/m²/s)"),
missing = "no") |>
add_p() |>
bold_labels()
# Exportar para Word (.docx)
tabela_final |>
as_flex_table() |>
flextable::save_as_docx(path = "tabela_co2.docx")
# Exportar para HTML
tabela_final |>
as_gt() |>
gt::gtsave(filename = "tabela_co2.html")| Formato | Função | Pacote necessário |
|---|---|---|
| Word (.docx) | as_flex_table() + save_as_docx() |
flextable |
| HTML | as_gt() + gtsave() |
gt |
| PDF (LaTeX) | as_kable_extra() |
kableExtra |
| RTF | as_flex_table() + save_as_rtf() |
flextable |
| Situação | Função indicada |
|---|---|
| Descrever as variáveis do dataset | tbl_summary() |
| Comparar dois ou mais grupos | tbl_summary(by = ) + add_p() |
| Apresentar coeficientes de regressão | tbl_regression() |
| Comparar dois modelos lado a lado | tbl_merge() |
| Empilhar tabelas de subgrupos | tbl_stack() |
| Reportar estatísticas no texto | inline_text() |
| Função | O que faz |
|---|---|
bold_labels() |
Negrito nos rótulos das variáveis |
bold_levels() |
Negrito nos níveis das variáveis categóricas |
bold_p() |
Negrito nos p-valores significativos |
italicize_labels() |
Itálico nos rótulos |
modify_header() |
Renomeia cabeçalhos das colunas |
add_overall() |
Adiciona coluna com estatísticas gerais |
add_n() |
Adiciona coluna com total de observações |
add_p() |
Adiciona coluna de p-valor com teste adequado |
add_difference() |
Adiciona diferença entre grupos com IC 95% |
add_glance_source_note() |
Adiciona métricas do modelo no rodapé |
label = antes de compartilhar a tabela. Nomes de variáveis como conc ou uptake não comunicam para o leitoradd_p() com consciência: o p-valor informa sobre significância, não sobre magnitude. Combine com add_difference() para reportar os dois| Situação | Problema | Solução |
|---|---|---|
| Tabela não aparece no Quarto | Output não compatível com o formato | Usar as_gt() para HTML e as_flex_table() para Word |
add_p() retorna aviso de tamanho de amostra |
Grupos pequenos para o teste padrão | Especificar test = list(all_continuous() ~ "wilcox.test") |
| Rótulos não aparecem | Argumento label com nome errado |
Verificar se o nome da variável está correto dentro de list() |
| Passo | Função | O que produz |
|---|---|---|
| 1 | tbl_summary() |
Tabela descritiva básica |
| 2 | statistic = + digits = |
Estatísticas personalizadas |
| 3 | label = + bold_labels() |
Rótulos profissionais |
| 4 | by = + add_p() + add_overall() |
Comparação entre grupos |
| 5 | add_difference() |
Diferença com IC 95% |
| 6 | tbl_regression() |
Tabela de regressão |
| 7 | add_glance_source_note() |
Métricas do modelo |
| 8 | tbl_merge() |
Modelos lado a lado |
| 9 | as_flex_table() + as_gt() |
Exportação |
tbl_summary(): danieldsjoberg.com/gtsummary/articles/tbl_summary.htmltbl_regression(): danieldsjoberg.com/gtsummary/articles/tbl_regression.htmlContinue praticando e explorando!
Esta aula é parte do projeto Café com R. É open source. Use, compartilhe e adapte.
Que cada gole desperte uma nova ideia. Que cada script abra uma nova conversa. Que o Café com R se torne um ponto de encontro nosso.

Jennifer Lopes | Café com R