Skip to contents

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 a parameterEstimates_table_list object which is a list of data frames, organized based on the sections for parameter estimates in the summary() output of lavaan, 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 a parameterEstimates_table_list object, with some degree of customization. Most of the customization should be done when calling parameterEstimates_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 in lavaan. Default is TRUE. Setting this to FALSE 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 calling summary() or lavaan::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.

Header or footer functions can be used to include a header or footer section. The first argument will be one of the following 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, and footer_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.