library(dplyr, warn.conflicts = FALSE) library(lme4) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "fig/README-" )
Over the years, I've written a lot of one-off functions for formatting numbers in RMarkdown documents. This packages collects them in a single location.
You can install printy from github with:
# install.packages("remotes") remotes::install_github("tjmahr/printy")
fmt_fix_digits()
prints a number with n digits of precision. R numbers lose
precision when converted to strings. This function converts the numbers to
strings and keeps precision. (It's a wrapper for sprintf()
.)
library(dplyr) library(printy) test_cor <- cor(mtcars[, 1:4]) # Typical loss of trailing zeroes test_cor[1:4, 3] |> round(2) |> as.character() test_cor[1:4, 3] |> fmt_fix_digits(2)
fmt_leading_zero()
removes a leading zero on numbers that are bounded between
โ1 and 1, such as correlations or p-values.
fmt_leading_zero(c(-0.3, 0.4, 1))
fmt_minus_sign()
formats negative numbers with a minus sign.
fmt_minus_sign(c(1, 2, -3, -0.4, -pi))
Putting it all together: Print a correlation matrix with 2 digits, no leading zero and with minus signs.
fmt_correlation <- function(xs, digits = 2) { xs |> fmt_fix_digits(digits) |> fmt_leading_zero() |> fmt_minus_sign() } test_cor |> as.data.frame() |> tibble::rownames_to_column(".rowname") |> tibble::as_tibble() |> mutate( across(-.rowname, fmt_correlation) ) |> rename(` ` = .rowname) |> knitr::kable(align = "lrrrr")
fmt_p_value()
formats p-values with n digits of precision, with no leading
zero, and with very small values being printed with a <
sign.
p <- c(1, 0.1, 0.01, 0.001, 0.0001) fmt_p_value(p, digits = 2) fmt_p_value(p, digits = 3)
fmt_p_value_md()
formats p-values in markdown with nice defaults.
p <- c(1, 0.1, 0.06, 0.059, 0.051, 0.01, 0.001, 0.0001) fmt_p_value_md(p)
These render as: r paste0(fmt_p_value_md(p), collapse = ", ")
.
fmt_effect_md()
is an experimental function for getting model effects
formatted in markdown. You give the function a model, an effect and a string
listing the quantities you want.
model <- lm(breaks ~ wool * tension, warpbreaks) summary(model)
# default to: b (beta), e (error), s (statistic), p (p value) fmt_effect_md(model, "woolB", "besp")
r fmt_effect_md(model, "woolB", "besp")
# Just a subset of them fmt_effect_md(model, "woolB", terms = "bp")
r fmt_effect_md(model, "woolB", terms = "bp")
# B for labeled b fmt_effect_md(model, "woolB", terms = "Bp", b_lab = "Wool B")
r fmt_effect_md(model, "woolB", terms = "Bp", b_lab = "Wool B")
# i for interval fmt_effect_md(model, "woolB", terms = "bi")
r fmt_effect_md(model, "woolB", terms = "bi")
# S for statistic with df fmt_effect_md(model, "woolB", terms = "bSp")
r fmt_effect_md(model, "woolB", terms = "bSp")
# extra digits (except for p-values; those go through `fmt_p_value_md()`) fmt_effect_md(model, "woolB", terms = "bep", digits = 6)
r fmt_effect_md(model, "woolB", terms = "bep", digits = 6)
These are the currently supported models:
lm()
lme4::lmer()
For lme4 models, Wald confidence intervals are provided. For p-values, the Kenwood--Roger approximation for the degrees of freedom is used by default. We can also choose a method supported by the parameters package.
library(lme4) data(Machines, package = "nlme") m <- lmer(score ~ 1 + Machine + (Machine | Worker), data = Machines) # Default is Kenward fmt_effect_md(m, "MachineB", terms = "beSp") fmt_effect_md(m, "MachineB", terms = "beSp", p_value_method = "kenward") # Note residual degrees of freedom for Wald fmt_effect_md(m, "MachineB", terms = "beSp", p_value_method = "wald") # This example doesn't find differences between Satterthwaite and Kenward fmt_effect_md(m, "MachineB", terms = "beSp", p_value_method = "satterthwaite")
We can also format effects from glmer()
models. "S"
is not supported because
the model summary uses z statistics, not t statistics.
gm1 <- glmer( cbind(incidence, size - incidence) ~ period + (1 | herd), data = cbpp, family = binomial ) round(coef(summary(gm1)), 3) fmt_effect_md(gm1, "period2", terms = "bespi") # Don't use S here fmt_effect_md(gm1, "period2", terms = "beSp")
I use fmt_
for formatting functions. The other convention in the package is
skel_
to plug values into a formatting skeleton.
skel_conf_interval_pair()
creates a confidence interval from two numbers.
skel_conf_interval_pair(c(1, 2))
skel_conf_interval()
is the vectorized version. It is suitable for working
on columns of numbers.
model <- lm(breaks ~ wool * tension, warpbreaks) ci_starts <- confint(model)[, 1] |> fmt_fix_digits(2) |> fmt_minus_sign() ci_ends <- confint(model)[, 2] |> fmt_fix_digits(2) |> fmt_minus_sign() skel_conf_interval(ci_starts, ci_ends)
skel_stat_n_value_pair()
creates t-test-like or correlation-like statistic
from a vector of two numbers.
skel_stat_n_value_pair(c("20", "2.0")) skel_stat_n_value_pair(c("39", ".98"), stat = "*r*")
skel_se()
and skel_ci()
are shorthand functions to help with inline
reporting.
skel_se(c(10, 4)) skel_ci(c("[1, 2]")) skel_ci(c("[1, 2]"), ci_width = 90)
One thing I've had to do a lot is summarize mixed effects models fit with lme4.
This package provides pretty_lme4_ranefs()
which creates a dataframe random
effect variances and covariances like those printed by summary()
.
For example, we can fit the model.
library(lme4) model <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy) summary(model)
pretty_lme4_ranefs()
creates the following dataframe.
pretty_lme4_ranefs(model)
Which in markdown renders as
knitr::kable( pretty_lme4_ranefs(model), align = c("l", "l", "r", "r", "r") )
Here's a dumb model with a lot going on in the random effects.
model <- lmer(mpg ~ wt * hp + (drat | gear) + (hp * cyl | am), mtcars) model knitr::kable( pretty_lme4_ranefs(model), align = c("l", "l", "r", "r", "r", "r", "r", "r", "r") )
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.