lavaan.printer
Shu Fai Cheung
lavaan.printer.Rmd
Introduction
This article illustrates how to use the two main functions of
lavaan.printer
:
These are the packages used in this article:
library(lavaan)
#> This is lavaan 0.6-18
#> lavaan is FREE software! Please report any bugs.
library(lavaan.printer)
For What Scenarios?
These two functions are not for end-users. They are for package
developers, and are intended to be used internally by
print
-methods or similar functions for the objects in other
packages which generate customized parameter tables.
parameterEstimates_table_list()
: creates aparameterEstimates_table_list
object which is a list of data frames, organized based on the sections for parameter estimates in thesummary()
output oflavaan
, such as factor loadings (Latent Variables
) and covariances (Covariances
). The data frames can be customized in a lot of ways, such as adding columns created by user-supplied functions, or adding header sections or footer sections.print_parameterEstimates_table_list()
: It prints aparameterEstimates_table_list
object, with some degree of customization. Most of the customization should be done when callingparameterEstimates_table_list()
. The cells are formatted as strings across sections when being printed to ensure that the column widths are consistent.
Scenarios
Create a List of Data frames
In the simplest case, parameterEstimates_table_list()
can be used to generate the usual parameter estimates results of
lavaan
, but as a list of data frames, each corresponding to
a section in the output (e.g., regression coefficients, factor
loadings). Arguments for to lavaan::parameterEstimates()
can be used when calling
parameterEstimates_table_list()
:
# Adapted from the example of cfa()
model_cfa <- "visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6"
fit <- cfa(model_cfa,
data = HolzingerSwineford1939,
group = "school")
est <- parameterEstimates_table_list(fit,
rsquare = TRUE)
Because it is intended to be used inside a print function, it does
not have a print method itself. Call
print_parameterEstimates_table_list()
instead:
print_parameterEstimates_table_list(est)
#>
#> Parameter Estimates Settings:
#>
#> Standard errors: Standard
#> Information: Expected
#> Information saturated (h1) model: Structured
#>
#> Group 1 [Pasteur]:
#> Latent Variables:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> visual =~
#> x1 1.000
#> x2 0.373 0.121 3.081 0.002 0.136 0.610
#> x3 0.541 0.141 3.843 0.000 0.265 0.817
#> textual =~
#> x4 1.000
#> x5 1.187 0.102 11.640 0.000 0.987 1.387
#> x6 0.870 0.076 11.372 0.000 0.720 1.020
#>
#> Group 1 [Pasteur]:
#> Covariances:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> visual ~~
#> textual 0.485 0.106 4.568 0.000 0.277 0.693
#>
#> Group 1 [Pasteur]:
#> Intercepts:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> .x1 4.941 0.095 52.249 0.000 4.756 5.127
#> .x2 5.984 0.098 60.949 0.000 5.792 6.176
#> .x3 2.487 0.093 26.778 0.000 2.305 2.669
#> .x4 2.823 0.092 30.689 0.000 2.642 3.003
#> .x5 3.995 0.105 38.183 0.000 3.790 4.200
#> .x6 1.922 0.079 24.321 0.000 1.767 2.077
#> visual 0.000
#> textual 0.000
#>
#> Group 1 [Pasteur]:
#> Variances:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> .x1 0.244 0.258 0.947 0.344 -0.262 0.750
#> .x2 1.344 0.158 8.498 0.000 1.034 1.653
#> .x3 1.009 0.138 7.317 0.000 0.739 1.279
#> .x4 0.424 0.069 6.105 0.000 0.288 0.560
#> .x5 0.445 0.086 5.161 0.000 0.276 0.614
#> .x6 0.297 0.051 5.864 0.000 0.197 0.396
#> visual 1.151 0.300 3.835 0.000 0.563 1.739
#> textual 0.896 0.150 5.967 0.000 0.602 1.190
#>
#> Group 1 [Pasteur]:
#> R-Squares:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> x1 0.825
#> x2 0.107
#> x3 0.250
#> x4 0.679
#> x5 0.740
#> x6 0.696
#>
#> Group 2 [Grant-White]:
#> Latent Variables:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> visual =~
#> x1 1.000
#> x2 0.813 0.175 4.657 0.000 0.471 1.155
#> x3 1.045 0.204 5.110 0.000 0.644 1.446
#> textual =~
#> x4 1.000
#> x5 0.981 0.086 11.351 0.000 0.812 1.151
#> x6 0.963 0.084 11.402 0.000 0.797 1.128
#>
#> Group 2 [Grant-White]:
#> Covariances:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> visual ~~
#> textual 0.377 0.096 3.941 0.000 0.189 0.564
#>
#> Group 2 [Grant-White]:
#> Intercepts:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> .x1 4.930 0.095 51.696 0.000 4.743 5.117
#> .x2 6.200 0.092 67.416 0.000 6.020 6.380
#> .x3 1.996 0.086 23.195 0.000 1.827 2.164
#> .x4 3.317 0.093 35.625 0.000 3.135 3.500
#> .x5 4.712 0.096 48.986 0.000 4.524 4.901
#> .x6 2.469 0.094 26.277 0.000 2.285 2.653
#> visual 0.000
#> textual 0.000
#>
#> Group 2 [Grant-White]:
#> Variances:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> .x1 0.792 0.132 6.017 0.000 0.534 1.050
#> .x2 0.878 0.124 7.104 0.000 0.636 1.120
#> .x3 0.498 0.114 4.386 0.000 0.276 0.721
#> .x4 0.310 0.065 4.776 0.000 0.183 0.437
#> .x5 0.429 0.073 5.900 0.000 0.287 0.572
#> .x6 0.402 0.069 5.818 0.000 0.267 0.537
#> visual 0.527 0.155 3.399 0.001 0.223 0.830
#> textual 0.947 0.153 6.196 0.000 0.648 1.247
#>
#> Group 2 [Grant-White]:
#> R-Squares:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> x1 0.399
#> x2 0.284
#> x3 0.536
#> x4 0.753
#> x5 0.680
#> x6 0.686
The output looks similar to the lavaan
output, except
for some minor changes in column names (e.g., CI.Lo
and
CI.Up
instead of ci.lower
and
ci.upper
) to shorten the width of the print, to make room
for additional columns developer may want to add. This is intentional:
mimicking the lavaan
style to minimize the need for the
users to learn anything new in reading the output.
These options are available in
print_parameterEstimates_table_list()
:
nd
: Control the number of digits after the decimal. Default is 3.by_group
: For multiple-group models, whether the tables are grouped by groups first, as inlavaan
. Default isTRUE
. Setting this toFALSE
facilitates comparing groups on estimates, especially when a model has a lot of parameters.drop_cols
: A character vector of columns to be dropped. Any columns can be dropped. Can be used to drop columns that cannot be removed when callingsummary()
orlavaan::parameterEstimates()
, or columns to be dropped only when being printed.na_str
: The string to be used for blank cells, such as the standard errors of fixed parameters. Default is" "
.
This is an example of these arguments:
print_parameterEstimates_table_list(est,
nd = 2,
by_group = FALSE,
drop_cols = "Z",
na_str = "--")
#>
#> Parameter Estimates Settings:
#>
#> Standard errors: Standard
#> Information: Expected
#> Information saturated (h1) model: Structured
#>
#> Latent Variables:
#> Group 1 [Pasteur]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> visual =~
#> x1 1.00 -- -- -- --
#> x2 0.37 0.12 0.00 0.14 0.61
#> x3 0.54 0.14 0.00 0.27 0.82
#> textual =~
#> x4 1.00 -- -- -- --
#> x5 1.19 0.10 0.00 0.99 1.39
#> x6 0.87 0.08 0.00 0.72 1.02
#>
#> Latent Variables:
#> Group 2 [Grant-White]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> visual =~
#> x1 1.00 -- -- -- --
#> x2 0.81 0.17 0.00 0.47 1.16
#> x3 1.04 0.20 0.00 0.64 1.45
#> textual =~
#> x4 1.00 -- -- -- --
#> x5 0.98 0.09 0.00 0.81 1.15
#> x6 0.96 0.08 0.00 0.80 1.13
#>
#> Covariances:
#> Group 1 [Pasteur]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> visual ~~
#> textual 0.49 0.11 0.00 0.28 0.69
#>
#> Covariances:
#> Group 2 [Grant-White]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> visual ~~
#> textual 0.38 0.10 0.00 0.19 0.56
#>
#> Intercepts:
#> Group 1 [Pasteur]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> .x1 4.94 0.09 0.00 4.76 5.13
#> .x2 5.98 0.10 0.00 5.79 6.18
#> .x3 2.49 0.09 0.00 2.31 2.67
#> .x4 2.82 0.09 0.00 2.64 3.00
#> .x5 4.00 0.10 0.00 3.79 4.20
#> .x6 1.92 0.08 0.00 1.77 2.08
#> visual 0.00 -- -- -- --
#> textual 0.00 -- -- -- --
#>
#> Intercepts:
#> Group 2 [Grant-White]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> .x1 4.93 0.10 0.00 4.74 5.12
#> .x2 6.20 0.09 0.00 6.02 6.38
#> .x3 2.00 0.09 0.00 1.83 2.16
#> .x4 3.32 0.09 0.00 3.13 3.50
#> .x5 4.71 0.10 0.00 4.52 4.90
#> .x6 2.47 0.09 0.00 2.28 2.65
#> visual 0.00 -- -- -- --
#> textual 0.00 -- -- -- --
#>
#> Variances:
#> Group 1 [Pasteur]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> .x1 0.24 0.26 0.34 -0.26 0.75
#> .x2 1.34 0.16 0.00 1.03 1.65
#> .x3 1.01 0.14 0.00 0.74 1.28
#> .x4 0.42 0.07 0.00 0.29 0.56
#> .x5 0.44 0.09 0.00 0.28 0.61
#> .x6 0.30 0.05 0.00 0.20 0.40
#> visual 1.15 0.30 0.00 0.56 1.74
#> textual 0.90 0.15 0.00 0.60 1.19
#>
#> Variances:
#> Group 2 [Grant-White]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> .x1 0.79 0.13 0.00 0.53 1.05
#> .x2 0.88 0.12 0.00 0.64 1.12
#> .x3 0.50 0.11 0.00 0.28 0.72
#> .x4 0.31 0.06 0.00 0.18 0.44
#> .x5 0.43 0.07 0.00 0.29 0.57
#> .x6 0.40 0.07 0.00 0.27 0.54
#> visual 0.53 0.15 0.00 0.22 0.83
#> textual 0.95 0.15 0.00 0.65 1.25
#>
#> R-Squares:
#> Group 1 [Pasteur]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> x1 0.82 -- -- -- --
#> x2 0.11 -- -- -- --
#> x3 0.25 -- -- -- --
#> x4 0.68 -- -- -- --
#> x5 0.74 -- -- -- --
#> x6 0.70 -- -- -- --
#>
#> R-Squares:
#> Group 2 [Grant-White]:
#> Estimate S.E. P(>|z|) CI.Lo CI.Up
#> x1 0.40 -- -- -- --
#> x2 0.28 -- -- -- --
#> x3 0.54 -- -- -- --
#> x4 0.75 -- -- -- --
#> x5 0.68 -- -- -- --
#> x6 0.69 -- -- -- --
Insert a Column Computed From Another Column
Suppose we would like to insert a column of symbols (e.g.,
"*"
and "**"
) into the parameter estimates
table based on the pvalue
column, to denote whether a
parameter is significant,
This is the function:
add_sig <- function(object,
breaks = c(1, .05, .01, .001, -Inf),
labels = c("***", "** ", "* ", " ")) {
tmp <- object[, "pvalue", drop = TRUE]
if (!is.null(tmp)) {
tmp[is.na(tmp)] <- 1
tmp2 <- cut(tmp,
breaks = breaks,
labels = labels)
i <- match("pvalue", colnames(object))
out <- data.frame(object[, 1:i],
Sig = tmp2,
object[, seq(i + 1, ncol(object))])
}
out
}
This can be done by the argument est_funs
:
model_cfa <- "visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6"
fit <- cfa(model_cfa,
data = HolzingerSwineford1939[1:100, ])
#> Warning: lavaan->lav_object_post_check():
#> some estimated ov variances are negative
est <- parameterEstimates_table_list(fit,
est_funs = list(add_sig))
print_parameterEstimates_table_list(est)
#>
#> Parameter Estimates Settings:
#>
#> Standard errors: Standard
#> Information: Expected
#> Information saturated (h1) model: Structured
#>
#> Latent Variables:
#> Estimate S.E. Z P(>|z|) Sig CI.Lo CI.Up
#> visual =~
#> x1 1.000
#> x2 0.163 0.118 1.379 0.168 -0.068 0.394
#> x3 0.355 0.192 1.849 0.065 -0.021 0.732
#> textual =~
#> x4 1.000
#> x5 1.202 0.129 9.322 0.000 *** 0.950 1.455
#> x6 0.707 0.081 8.694 0.000 *** 0.548 0.867
#>
#> Covariances:
#> Estimate S.E. Z P(>|z|) Sig CI.Lo CI.Up
#> visual ~~
#> textual 0.430 0.123 3.485 0.000 *** 0.188 0.672
#>
#> Variances:
#> Estimate S.E. Z P(>|z|) Sig CI.Lo CI.Up
#> .x1 -0.257 0.793 -0.324 0.746 -1.810 1.297
#> .x2 1.341 0.190 7.055 0.000 *** 0.969 1.714
#> .x3 1.022 0.175 5.828 0.000 *** 0.678 1.366
#> .x4 0.331 0.076 4.372 0.000 *** 0.183 0.479
#> .x5 0.405 0.103 3.929 0.000 *** 0.203 0.607
#> .x6 0.241 0.046 5.291 0.000 *** 0.152 0.331
#> visual 1.622 0.814 1.992 0.046 * 0.026 3.219
#> textual 0.812 0.166 4.899 0.000 *** 0.487 1.137
Note that est_funs
must be a list, even if only one
function is supplied.
Add a Header or Footer Section
Header or footer functions can be used to include a header or footer section. The first argument will be one of the following object:
If the input object of
parameterEstimates_table_list()
is alavaan
object, then the function is called with the first argument being the parameter estimates table generated bylavaan::parameterEstimates()
) withoutput = "text", header = TRUE
.If the input object of
parameterEstimates_table_list()
is a data-frame-like object, such as a modified output oflavaan::parameterEstimates()
generated by other functions, then the function is called with this object as the first argument. Header and footer sections can then be created using attributes stored in this object.
The following is a simple function to print the missing data handling
method, stored in the output of
lavaan::parameterEstimates()
when printed with
output = "text", header = "TRUE"
. The attribute
section_title
is used to set the title for this section. By
default, print()
will be used to print a section.
lavaan_missing <- function(x) {
out0 <- attr(x, "missing")
out1 <- data.frame(Option = "Missing",
Setting = out0)
attr(out1, "section_title") <- "Additional Information:"
out1
}
This is a function to add some footnotes. The output is a character
vector, which should be printed by cat()
. This can be done
by setting the attribute print_fun
to "cat"
.
If the print function is cat()
, the section is printed with
sep = "\n"
by default.
footnotes <- function(x) {
out0 <- c("- This is footnote 1.",
paste("- This is footnote 2, a very very very very very",
"very very very very very very very very very very",
"very very long one. Wrapped by default"))
attr(out0, "section_title") <- "Footnote:"
attr(out0, "print_fun") <- "cat"
out0
}
These functions can then be used in header_funs
and
footer_funs
:
model_cfa <- "visual =~ x1 + x2 + x3"
fit <- cfa(model_cfa,
data = HolzingerSwineford1939)
est <- parameterEstimates_table_list(fit,
header_funs = list(lavaan_missing),
footer_funs = list(footnotes))
print_parameterEstimates_table_list(est)
#>
#> Additional Information:
#> Option Setting
#> Missing listwise
#>
#> Parameter Estimates Settings:
#>
#> Standard errors: Standard
#> Information: Expected
#> Information saturated (h1) model: Structured
#>
#> Latent Variables:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> visual =~
#> x1 1.000
#> x2 0.778 0.141 5.532 0.000 0.502 1.053
#> x3 1.107 0.214 5.173 0.000 0.688 1.527
#>
#> Variances:
#> Estimate S.E. Z P(>|z|) CI.Lo CI.Up
#> .x1 0.835 0.118 7.064 0.000 0.603 1.066
#> .x2 1.065 0.105 10.177 0.000 0.860 1.270
#> .x3 0.633 0.129 4.899 0.000 0.380 0.886
#> visual 0.524 0.130 4.021 0.000 0.268 0.779
#>
#> Footnote:
#> - This is footnote 1.
#> - This is footnote 2, a very very very very very very very very very
#> very very very very very very very very long one. Wrapped by default
Like est_funs
, the value of header_funs
(and footer_funs
) must be list.
Further Information
There are other ways to customize the output when calling
parameterEstimates_table_list()
. For example:
Drop one or more columns.
Rename one or more columns.
Set arguments when calling functions in
est_funs
,header_funs
, andfooter_funs
.
Please refer to the help page of
parameterEstimates_table_list()
for details.
Issues
If you have any suggestions and found any bugs, please feel feel to open a GitHub issue. Thanks.