-
Notifications
You must be signed in to change notification settings - Fork 5
/
README.Rmd
297 lines (211 loc) · 6.84 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
---
output:
github_document:
default
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, include = FALSE}
library(dplyr, warn.conflicts = FALSE)
library(lme4)
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "fig/README-"
)
```
# printy
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.
## Installation 📚
You can install printy from github with:
```{r gh-installation, eval = FALSE}
# install.packages("remotes")
remotes::install_github("tjmahr/printy")
```
## Formatters ✍
`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()`.)
```{r fix-digits}
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.
```{r leading-zero}
fmt_leading_zero(c(-0.3, 0.4, 1))
```
`fmt_minus_sign()` formats negative numbers with a minus sign.
```{r 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.
```{r}
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")
```
### *p*-values 🎣
`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.
```{r}
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.
* Use 3 digits of precision for values less than .06
* Otherwise, use 2 digits of precision.
* Include *p* in markdown
```{r}
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 = ", ")`.
### Experimental formatters 🧪
`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.
```{r}
model <- lm(breaks ~ wool * tension, warpbreaks)
summary(model)
```
```{r}
# default to: b (beta), e (error), s (statistic), p (p value)
fmt_effect_md(model, "woolB", "besp")
```
`r fmt_effect_md(model, "woolB", "besp")`
```{r}
# Just a subset of them
fmt_effect_md(model, "woolB", terms = "bp")
```
`r fmt_effect_md(model, "woolB", terms = "bp")`
```{r}
# 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")`
```{r bi}
# i for interval
fmt_effect_md(model, "woolB", terms = "bi")
```
`r fmt_effect_md(model, "woolB", terms = "bi")`
```{r bSp}
# S for statistic with df
fmt_effect_md(model, "woolB", terms = "bSp")
```
`r fmt_effect_md(model, "woolB", terms = "bSp")`
```{r}
# 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](https://easystats.github.io/parameters/reference/p_value.lmerMod.html).
```{r}
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.
```{r, error = TRUE}
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")
```
Skeletons 🦴
-----------------------------------------------------------------------
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.
```{r}
skel_conf_interval_pair(c(1, 2))
```
`skel_conf_interval()` is the vectorized version. It is suitable for working
on columns of numbers.
```{r}
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.
```{r}
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.
```{r}
skel_se(c(10, 4))
skel_ci(c("[1, 2]"))
skel_ci(c("[1, 2]"), ci_width = 90)
```
## Formatting tables from lme4 models 🖇
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.
```{r}
library(lme4)
model <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy)
summary(model)
```
`pretty_lme4_ranefs()` creates the following dataframe.
```{r}
pretty_lme4_ranefs(model)
```
Which in markdown renders as
```{r}
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.
```{r, warning = FALSE}
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")
)
```