# Penalized Factor Analysis

## Introduction

Aim. This vignette shows how to fit a penalized factor analysis model using the routines in the `penfa` package. The penalty will automatically introduce sparsity in the factor loading matrix.

Data. For illustration purposes, we use the cross-cultural data set `ccdata` containing the standardized ratings to 12 items concerning organizational citizenship behavior. Employees from different countries were asked to rate their attitudes towards helping other employees and giving suggestions for improved work conditions. The items are thought to measure two latent factors: help, defined by the first seven items (`h1` to `h7`), and voice, represented by the last five items (`v1` to `v5`). See `?ccdata` for details.

This data set is a standardized version of the one in the `ccpsyc` package, and only considers employees from Lebanon and Taiwan (i.e., `"LEB"`, `"TAIW"`). This vignette is meant as a demo of the capabilities of `penfa`; please refer to Fischer et al. (2019) and Fischer and Karl (2019) for a description and analysis of these data.

Let us load and inspect `ccdata`.

    library(penfa)
    data(ccdata)

    summary(ccdata)
    ##    country                h1                 h2                h3                 h4
    ##  Length:767         Min.   :-2.62004   Min.   :-2.9034   Min.   :-2.63082   Min.   :-3.0441
    ##  Class :character   1st Qu.:-0.69516   1st Qu.:-0.2163   1st Qu.:-0.70356   1st Qu.:-0.2720
    ##  Mode  :character   Median :-0.05354   Median : 0.4554   Median :-0.06114   Median : 0.4211
    ##                     Mean   : 0.00000   Mean   : 0.0000   Mean   : 0.00000   Mean   : 0.0000
    ##                     3rd Qu.: 0.58809   3rd Qu.: 0.4554   3rd Qu.: 0.58128   3rd Qu.: 0.4211
    ##                     Max.   : 1.22971   Max.   : 1.1272   Max.   : 1.22370   Max.   : 1.1141
    ##        h5                h6                h7                v1                  v2
    ##  Min.   :-2.9105   Min.   :-2.9541   Min.   :-2.8364   Min.   :-2.627694   Min.   :-2.674430
    ##  1st Qu.:-0.8662   1st Qu.:-0.9092   1st Qu.:-0.7860   1st Qu.:-0.660770   1st Qu.:-0.671219
    ##  Median : 0.4966   Median : 0.4541   Median :-0.1025   Median :-0.005129   Median :-0.003482
    ##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.000000   Mean   : 0.000000
    ##  3rd Qu.: 0.4966   3rd Qu.: 0.4541   3rd Qu.: 0.5810   3rd Qu.: 0.650512   3rd Qu.: 0.664255
    ##  Max.   : 1.1781   Max.   : 1.1358   Max.   : 1.2645   Max.   : 1.306154   Max.   : 1.331992
    ##        v3                 v4                 v5
    ##  Min.   :-2.65214   Min.   :-2.65722   Min.   :-2.51971
    ##  1st Qu.:-0.68800   1st Qu.:-0.68041   1st Qu.:-0.61127
    ##  Median :-0.03329   Median :-0.02148   Median : 0.02488
    ##  Mean   : 0.00000   Mean   : 0.00000   Mean   : 0.00000
    ##  3rd Qu.: 0.62142   3rd Qu.: 0.63746   3rd Qu.: 0.66103
    ##  Max.   : 1.27613   Max.   : 1.29639   Max.   : 1.29718

## Model specification

Before fitting the model, we need to write a model syntax describing the relationships between the items and the latent factors. To facilitate its formulation, the rules for the syntax specification broadly follow the ones required by lavaan. The syntax must be enclosed in single quotes `' '`.

    syntax = 'help  =~   h1 + h2 + h3 + h4 + h5 + h6 + h7 + 0*v1 + v2 + v3 + v4 + v5
              voice =~ 0*h1 + h2 + h3 + h4 + h5 + h6 + h7 +   v1 + v2 + v3 + v4 + v5'

The factors `help` and `voice` appear on the left-hand side, whereas the observed variables on the left-hand side. Following the rationale in Geminiani et al. (2021), we only specify the minimum number of identification constraints. We are setting the scales of the factors by fixing their factor variances to 1. This can be done in one of two ways: 1) by adding `'help ~~ 1*help'` and `'voice ~~ 1*voice'` to the syntax above; or 2) by setting the argument `std.lv = TRUE` in the fitting function (see below). To avoid rotational freedom, we fix one loading per factor to zero. Parameters can be easily fixed to user-defined values through the pre-multiplication mechanism. By default, unique variances are automatically added to the model, and the factors are allowed to correlate. These specifications can be modified by altering the syntax (see `?penfa` for details on how to write the model syntax).

## Model fitting

The core of the package is given by the `penfa` function, a short form for PENalized Factor Analysis, that implements the framework discussed in Geminiani et al. (2021). By default, it employs the automatic procedure for the optimal selection of the tuning parameter(s), and the default value of the influence factor is 4. If needed, these choices can be altered by changing the values of the corresponding arguments (`strategy` and `gamma`) in the function call (see `?penfa` and `?penfaOptions` for details).

The `penfa` function allows users to choose among a variety of penalty functions, including lasso, adaptive lasso (alasso), smoothly clipped absolute deviation (scad), minimax concave penalty (mcp), and ridge. Except for the latter, these penalties can produce sparse estimates. For the sake of completeness, `penfa` can also estimate an unpenalized model. In this vignette, we show how users can estimate a single-group penalized factor model with the lasso and alasso penalty. Before jumping to the penalization though, the next section illustrates the estimation of an unpenalized model, which is a necessary step for obtaining the adaptive weights demanded by the alasso.

### Unpenalized (MLE) model

The `penfa` function can also be used to estimate a factor model by ordinary maximum likelihood. The first argument is the user-specified model `syntax`, followed by the data set `ccdata` with the observed variables. The scales of the latent factors are specified by setting `std.lv = TRUE`. Because no penalization is required, the shrinkage penalty `pen.shrink` is set to `"none"`. The `eta` argument relates to the tuning parameter, so in this case it is set to zero. The argument `strategy = "fixed"` prompts the estimation of the model with the value of the tuning parameter in `eta`. By default, the Fisher information is used in the trust-region algorithm. Some messages on convergence and admissibility are shown by default; setting `verbose = FALSE` prevents printed output.

    mle.fit <- penfa(## factor model
                     model = syntax,
                     data  = ccdata,
                     std.lv = TRUE,
                     ## (no) penalization
                     pen.shrink = "none",
                     eta = list(shrink = c("none" = 0), diff = c("none" = 0)),
                     strategy = "fixed")
    ##
    ## Largest absolute gradient value: 0.00108660
    ## Fisher information matrix is positive definite
    ## Eigenvalue range: [23.07573, 11057.36]
    ## Trust region iterations: 18
    ## Factor solution: admissible
    ## Computing VCOV ... done.
    ## Effective degrees of freedom: 35

The trust-region algorithm required a small number of iterations to converge. Since no penalization is imposed, the effective degrees of freedom (edf) coincide with the number of parameters. The estimated parameters can be extracted via the `coef` method. We collect them in the `mle.weights` vector, which will be used when fitting the penalized model with the alasso penalty.

    mle.weights <- coef(mle.fit)

The `penfaOut` function can be called to have a quick look at the estimated parameter matrices. We notice that there are a couple of cross-loadings. In this case, it is convenient to resort to penalized factor analysis to encourage sparsity in the factor loading matrix through a shrinkage penalty function.

    penfaOut(mle.fit)
    ## $lambda
    ##      help  voice
    ## h1  0.782  0.000
    ## h2  0.905 -0.031
    ## h3  0.779  0.014
    ## h4  0.986 -0.093
    ## h5  0.783  0.100
    ## h6  0.770  0.136
    ## h7  0.530  0.354
    ## v1  0.000  0.870
    ## v2  0.055  0.837
    ## v3  0.053  0.810
    ## v4  0.013  0.850
    ## v5 -0.004  0.827
    ##
    ## $psi
    ##       h1    h2    h3    h4    h5    h6    h7    v1    v2    v3    v4    v5
    ## h1 0.387 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
    ## h2 0.000 0.229 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
    ## h3 0.000 0.000 0.373 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
    ## h4 0.000 0.000 0.000 0.177 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
    ## h5 0.000 0.000 0.000 0.000 0.238 0.000 0.000 0.000 0.000 0.000 0.000 0.000
    ## h6 0.000 0.000 0.000 0.000 0.000 0.204 0.000 0.000 0.000 0.000 0.000 0.000
    ## h7 0.000 0.000 0.000 0.000 0.000 0.000 0.265 0.000 0.000 0.000 0.000 0.000
    ## v1 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.242 0.000 0.000 0.000 0.000
    ## v2 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.213 0.000 0.000 0.000
    ## v3 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.265 0.000 0.000
    ## v4 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.256 0.000
    ## v5 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.321
    ##
    ## $phi
    ##        help voice
    ## help  1.000 0.875
    ## voice 0.875 1.000

### Lasso

We start off with the lasso, one of the simplest and widely-known penalty functions. In the function call, we now specify `pen.shrink = "lasso"`, and we provide through the `eta` argument a starting value for the tuning parameter (here 0.01) required by the automatic procedure (`strategy = "auto"`). The name given to the starting value (here, the factor loading matrix `"lambda"`) reflects the parameter matrix to be penalized. All of its elements are penalized, which means here that the penalization is applied to all factor loadings (except the ones fixed for identification). See `?penfaOptions` for additional details on the available options.

    lasso.fit <- penfa(## factor model
                       model  = syntax,
                       data   = ccdata,
                       std.lv = TRUE,
                       ## penalization
                       pen.shrink = "lasso",
                       eta = list(shrink = c("lambda" = 0.01), diff = c("none" = 0)),
                       ## automatic procedure
                       strategy = "auto")
    ##
    ## Automatic procedure:
    ## Iteration  1 : 0.01403787
    ##
    ## Largest absolute gradient value: 3.10138821
    ## Fisher information matrix is positive definite
    ## Eigenvalue range: [152.9943, 90518.23]
    ## Trust region iterations: 16
    ## Factor solution: admissible
    ## Effective degrees of freedom: 29.93813

The `summary` method details information on the model characteristics, the optimization and penalization procedures as well as the parameter estimates with associated standard errors and confidence intervals. The optimal value of the tuning parameter for this lasso-penalized factor model is 0.014. The Type column distinguishes between the fixed parameters set to specific values for identification, the free parameters that have been estimated through ordinary maximum likelihood, and the penalized (pen) parameters. The standard errors here have been computed as the square root of the inverse of the penalized Fisher information matrix (Geminiani et al., 2021). The last columns report 95% confidence intervals (CI) for the model parameters. Standard errors and CI of the penalized parameters shrunken to zero are not displayed. A different significance level can be specified through the `level` argument in the `summary` call.

    summary(lasso.fit)
    ## penfa 0.1.1 reached convergence
    ##
    ##   Number of observations                                    767
    ##   Number of groups                                            1
    ##   Number of observed variables                               12
    ##   Number of latent factors                                    2
    ##
    ##   Estimator                                                PMLE
    ##   Optimization method                              trust-region
    ##   Information                                            fisher
    ##   Strategy                                                 auto
    ##   Number of iterations (total)                               32
    ##   Number of two-steps (automatic)                             1
    ##   Influence factor                                            4
    ##   Number of parameters:
    ##     Free                                                     13
    ##     Penalized                                                22
    ##   Effective degrees of freedom                           29.938
    ##   GIC                                                 17227.673
    ##   GBIC                                                17366.660
    ##
    ##   Penalty function:
    ##     Sparsity                                              lasso
    ##
    ##   Optimal tuning parameter:
    ##     Sparsity
    ##      - Factor loadings                                    0.014
    ##
    ##
    ## Parameter Estimates:
    ##
    ## Latent Variables:
    ##                     Type    Estimate  Std.Err     2.5%    97.5%
    ##   help =~
    ##     h1               pen       0.748    0.030    0.691    0.806
    ##     h2               pen       0.835    0.033    0.770    0.900
    ##     h3               pen       0.718    0.048    0.624    0.811
    ##     h4               pen       0.884    0.041    0.805    0.964
    ##     h5               pen       0.717    0.047    0.625    0.810
    ##     h6               pen       0.706    0.045    0.617    0.795
    ##     h7               pen       0.483    0.046    0.392    0.574
    ##     v1             fixed       0.000             0.000    0.000
    ##     v2               pen       0.042
    ##     v3               pen       0.040
    ##     v4               pen       0.009
    ##     v5               pen       0.000
    ##   voice =~
    ##     h1             fixed       0.000             0.000    0.000
    ##     h2               pen       0.006
    ##     h3               pen       0.044
    ##     h4               pen      -0.022
    ##     h5               pen       0.132    0.045    0.044    0.219
    ##     h6               pen       0.166    0.043    0.081    0.250
    ##     h7               pen       0.365    0.046    0.274    0.456
    ##     v1               pen       0.832    0.028    0.778    0.887
    ##     v2               pen       0.812    0.044    0.726    0.898
    ##     v3               pen       0.784    0.045    0.697    0.872
    ##     v4               pen       0.816    0.036    0.745    0.887
    ##     v5               pen       0.786    0.029    0.730    0.843
    ##
    ## Covariances:
    ##                     Type    Estimate  Std.Err     2.5%    97.5%
    ##   help ~~
    ##     voice           free       0.855    0.015    0.825    0.884
    ##
    ## Variances:
    ##                     Type    Estimate  Std.Err     2.5%    97.5%
    ##    .h1              free       0.384    0.021    0.342    0.426
    ##    .h2              free       0.228    0.014    0.200    0.256
    ##    .h3              free       0.372    0.021    0.331    0.413
    ##    .h4              free       0.181    0.013    0.156    0.206
    ##    .h5              free       0.239    0.014    0.211    0.267
    ##    .h6              free       0.204    0.012    0.180    0.228
    ##    .h7              free       0.265    0.015    0.236    0.293
    ##    .v1              free       0.243    0.015    0.213    0.273
    ##    .v2              free       0.212    0.014    0.185    0.239
    ##    .v3              free       0.265    0.016    0.233    0.297
    ##    .v4              free       0.257    0.016    0.226    0.289
    ##    .v5              free       0.322    0.019    0.285    0.359
    ##     help           fixed       1.000             1.000    1.000
    ##     voice          fixed       1.000             1.000    1.000

### Alasso

The potential problem with the lasso is its bias issue. To solve the problem, researchers have formulated the so-called oracle penalties, which include the alasso, scad, and mcp.

Since the scad and mcp cannot be used with the automatic procedure (model fitting is only possible for a fixed tuning value), we illustrate here the estimation process with the alasso penalty. As previously mentioned, the alasso requires a vector of adaptive weights. Although the `penfa` function can internally compute an unpenalized model to get these values, users can easily pass their own vector of values through the `weights` argument. The alasso relies on an additional tuning parameter (the exponent value). By default its value is set to 1, but users can increase it to encourage more sparsity (e.g., set `a.alasso = 2` in the `penfa` call).

    alasso.fit <- penfa(## factor model
                        model  = syntax,
                        data   = ccdata,
                        std.lv = TRUE,
                        ## penalization
                        pen.shrink = "alasso",
                        eta = list(shrink = c("lambda" = 0.01), diff = c("none" = 0)),
                        ## automatic procedure
                        strategy = "auto",
                        gamma = 4,
                        ## alasso
                        weights = mle.weights,
                        verbose = FALSE)
    alasso.fit
    ## penfa 0.1.1 reached convergence
    ##
    ##   Number of observations                                    767
    ##
    ##   Estimator                                                PMLE
    ##   Optimization method                              trust-region
    ##   Information                                            fisher
    ##   Strategy                                                 auto
    ##   Number of iterations (total)                               58
    ##   Number of two-steps (automatic)                             2
    ##   Effective degrees of freedom                           27.129
    ##
    ##   Penalty function:
    ##     Sparsity                                             alasso
    ##
    ##

The printed output gives an overview of the data and the optimization process, including the employed optimizer and penalty function, the total number of iterations and the number of outer iterations of the automatic procedure. The automatic procedure is very fast, as it required a couple of iterations to reach convergence.

#### Effective degrees of freedom

The number of edf of this penalized model is 27.129, which is a fractional number, and is the sum of the contributions from the edf of each parameter.

    alasso.fit@Inference$edf.single
    ##     help=~h1     help=~h2     help=~h3     help=~h4     help=~h5     help=~h6
    ## 0.9947715501 0.9964627359 0.9948763923 0.9945258788 0.9914179923 0.9889262380
    ##     help=~h7     help=~v2     help=~v3     help=~v4     help=~v5    voice=~h2
    ## 0.9692182373 0.0006292259 0.0005203556 0.0001223770 0.0000319953 0.0003120181
    ##    voice=~h3    voice=~h4    voice=~h5    voice=~h6    voice=~h7    voice=~v1
    ## 0.0001076611 0.2901653639 0.3585496918 0.6371332419 0.9316357847 0.9962322251
    ##    voice=~v2    voice=~v3    voice=~v4    voice=~v5       h1~~h1       h2~~h2
    ## 0.9963020143 0.9958467402 0.9960609299 0.9955077902 1.0000000000 1.0000000000
    ##       h3~~h3       h4~~h4       h5~~h5       h6~~h6       h7~~h7       v1~~v1
    ## 1.0000000000 1.0000000000 1.0000000000 1.0000000000 1.0000000000 1.0000000000
    ##       v2~~v2       v3~~v3       v4~~v4       v5~~v5  help~~voice
    ## 1.0000000000 1.0000000000 1.0000000000 1.0000000000 1.0000000000

#### Summary

    summary(alasso.fit)
    ## penfa 0.1.1 reached convergence
    ##
    ##   Number of observations                                    767
    ##   Number of groups                                            1
    ##   Number of observed variables                               12
    ##   Number of latent factors                                    2
    ##
    ##   Estimator                                                PMLE
    ##   Optimization method                              trust-region
    ##   Information                                            fisher
    ##   Strategy                                                 auto
    ##   Number of iterations (total)                               58
    ##   Number of two-steps (automatic)                             2
    ##   Influence factor                                            4
    ##   Number of parameters:
    ##     Free                                                     13
    ##     Penalized                                                22
    ##   Effective degrees of freedom                           27.129
    ##   GIC                                                 17222.980
    ##   GBIC                                                17348.928
    ##
    ##   Penalty function:
    ##     Sparsity                                             alasso
    ##
    ##   Additional tuning parameter
    ##     alasso                                                    1
    ##
    ##   Optimal tuning parameter:
    ##     Sparsity
    ##      - Factor loadings                                    0.005
    ##
    ##
    ## Parameter Estimates:
    ##
    ## Latent Variables:
    ##                     Type    Estimate  Std.Err     2.5%    97.5%
    ##   help =~
    ##     h1               pen       0.766    0.030    0.707    0.825
    ##     h2               pen       0.858    0.028    0.803    0.913
    ##     h3               pen       0.775    0.030    0.717    0.834
    ##     h4               pen       0.921    0.038    0.847    0.995
    ##     h5               pen       0.810    0.040    0.732    0.887
    ##     h6               pen       0.782    0.044    0.696    0.868
    ##     h7               pen       0.523    0.050    0.426    0.620
    ##     v1             fixed       0.000             0.000    0.000
    ##     v2               pen       0.000
    ##     v3               pen       0.000
    ##     v4               pen       0.000
    ##     v5               pen      -0.000
    ##   voice =~
    ##     h1             fixed       0.000             0.000    0.000
    ##     h2               pen      -0.000
    ##     h3               pen       0.000
    ##     h4               pen      -0.041
    ##     h5               pen       0.053    0.031   -0.008    0.114
    ##     h6               pen       0.104    0.038    0.029    0.180
    ##     h7               pen       0.341    0.049    0.246    0.437
    ##     v1               pen       0.851    0.028    0.795    0.906
    ##     v2               pen       0.871    0.028    0.817    0.926
    ##     v3               pen       0.842    0.029    0.786    0.898
    ##     v4               pen       0.843    0.029    0.787    0.899
    ##     v5               pen       0.805    0.029    0.747    0.862
    ##
    ## Covariances:
    ##                     Type    Estimate  Std.Err     2.5%    97.5%
    ##   help ~~
    ##     voice           free       0.877    0.011    0.855    0.900
    ##
    ## Variances:
    ##                     Type    Estimate  Std.Err     2.5%    97.5%
    ##    .h1              free       0.388    0.021    0.346    0.429
    ##    .h2              free       0.233    0.014    0.205    0.261
    ##    .h3              free       0.372    0.021    0.332    0.413
    ##    .h4              free       0.184    0.012    0.160    0.209
    ##    .h5              free       0.235    0.014    0.207    0.263
    ##    .h6              free       0.201    0.012    0.177    0.225
    ##    .h7              free       0.264    0.015    0.235    0.293
    ##    .v1              free       0.245    0.015    0.216    0.275
    ##    .v2              free       0.208    0.014    0.182    0.235
    ##    .v3              free       0.261    0.016    0.230    0.292
    ##    .v4              free       0.259    0.016    0.228    0.290
    ##    .v5              free       0.324    0.019    0.287    0.361
    ##     help           fixed       1.000             1.000    1.000
    ##     voice          fixed       1.000             1.000    1.000

The model produced a clear simple structure with the exception of a cross-loading for `h7` on the `voice` factor. The alasso penalty managed to set non-relevant loadings to zero without affecting the relevant coefficients.

If users desire solutions sparser than the ones produced by default, they can increase the value of the influence factor (e.g., `gamma = 4.5`; by default `gamma = 4`) or the exponent of the alasso (e.g., `a.alasso = 2`; by default `a.alasso = 1`). Conversely, if the obtained solution is deemed too sparse, the value of the influence factor can possibly be decreased up to 1.

In order to evaluate and choose among different penalized factor solutions, users can inspect the values of the generalized information criteria. In sparse settings, the GBIC (Generalized Bayesian Information criterion) is recommended. The GBIC can be retrieved from `alasso.fit@Inference$IC$BIC` or through the `BIC` function:

    BIC(alasso.fit)
    ## [1] 17348.93

Similarly, `AIC(alasso.fit)` gives the GIC (Generalized Information Criterion), and `logLik(alasso.fit)` the model log-likelihood (without the penalty term).

#### Implied moments

The implied moments (here, the covariance matrix) can be found via the `fitted` method.

    implied <- fitted(alasso.fit)
    implied
    ## $cov
    ##    h1    h2    h3    h4    h5    h6    h7    v1    v2    v3    v4    v5
    ## h1 0.974
    ## h2 0.657 0.969
    ## h3 0.594 0.665 0.973
    ## h4 0.678 0.759 0.686 0.968
    ## h5 0.655 0.734 0.664 0.757 0.968
    ## h6 0.669 0.749 0.677 0.772 0.749 0.966
    ## h7 0.630 0.706 0.638 0.724 0.708 0.727 0.967
    ## v1 0.571 0.640 0.579 0.652 0.649 0.672 0.681 0.969
    ## v2 0.585 0.656 0.593 0.668 0.665 0.689 0.697 0.741 0.968
    ## v3 0.566 0.634 0.573 0.645 0.642 0.665 0.674 0.716 0.734 0.970
    ## v4 0.566 0.634 0.573 0.646 0.643 0.666 0.674 0.717 0.735 0.710 0.970
    ## v5 0.541 0.606 0.547 0.617 0.614 0.636 0.644 0.685 0.701 0.678 0.678 0.972

#### Penalty matrix

The penalty matrix is stored in `alasso.fit@Penalize@Sh.info$S.h`. Alternatively, it can be extracted via the `penmat` function (see below).

    alasso_penmat <- penmat(alasso.fit)

The penalty matrix is diagonal with elements quantifying the extent to which each model parameters has been penalized. The values corresponding to the factor loadings are different from zero, as these are the penalized parameters, whereas the values for the unique variances (`h1~~h1` to `v5~~v5`) and the factor covariance (`help~~voice`) are zero, as these elements were not affected by the penalization. The magnitude of the penalization varies depending on the size of the loading to be penalized: small loadings received a considerable penalty, whereas large loadings a little one.

    diag(alasso_penmat)

    ##    help=~h1    help=~h2    help=~h3    help=~h4    help=~h5    help=~h6
    ##        5.80        4.47        5.75        3.82        5.47        5.76
    ##    help=~h7    help=~v2    help=~v3    help=~v4    help=~v5   voice=~h2
    ##       12.52   581469.16   638625.57  2723361.23  9187629.45  1097206.61
    ##   voice=~h3   voice=~h4   voice=~h5   voice=~h6   voice=~h7   voice=~v1
    ##  2457115.80      908.38      662.82      245.05       28.77        4.69
    ##   voice=~v2   voice=~v3   voice=~v4   voice=~v5      h1~~h1      h2~~h2
    ##        4.76        5.09        4.84        5.22        0.00        0.00
    ##      h3~~h3      h4~~h4      h5~~h5      h6~~h6      h7~~h7      v1~~v1
    ##        0.00        0.00        0.00        0.00        0.00        0.00
    ##      v2~~v2      v3~~v3      v4~~v4      v5~~v5 help~~voice
    ##        0.00        0.00        0.00        0.00        0.00

See “plotting-penalty-matrix” for details on how to produce an interactive plot of the penalty matrix.

#### Factor scores

Lastly, the factor scores can be calculated via the `penfaPredict` function.

    fscores <- penfaPredict(alasso.fit)
    head(fscores)
    ##             help      voice
    ## [1,] -0.44516742  0.1487113
    ## [2,] -0.09050701 -0.3588310
    ## [3,]  0.57579146  0.7056186
    ## [4,]  0.11063667  0.6259668
    ## [5,]  0.38037518  0.8808153
    ## [6,] -0.64225773 -0.4877660

## R Session

    sessionInfo()
    ## R version 4.1.0 (2021-05-18)
    ## Platform: x86_64-w64-mingw32/x64 (64-bit)
    ## Running under: Windows 10 x64 (build 19042)
    ##
    ## Matrix products: default
    ##
    ## locale:
    ## [1] LC_COLLATE=English_United States.1252
    ## [2] LC_CTYPE=English_United States.1252
    ## [3] LC_MONETARY=English_United States.1252
    ## [4] LC_NUMERIC=C
    ## [5] LC_TIME=English_United States.1252
    ##
    ## attached base packages:
    ## [1] stats     graphics  grDevices utils     datasets  methods   base
    ##
    ## other attached packages:
    ## [1] penfa_0.1.1
    ##
    ## loaded via a namespace (and not attached):
    ##  [1] VineCopula_2.4.2    magic_1.5-9         sass_0.4.0
    ##  [4] VGAM_1.1-5          sfsmisc_1.1-11      jsonlite_1.7.2
    ##  [7] splines_4.1.0       tmvnsim_1.0-2       distr_2.8.0
    ## [10] bslib_0.2.5.1       assertthat_0.2.1    stats4_4.1.0
    ## [13] yaml_2.2.1          numDeriv_2016.8-1.1 pillar_1.6.1
    ## [16] lattice_0.20-44     startupmsg_0.9.6    glue_1.4.2
    ## [19] digest_0.6.27       colorspace_2.0-2    htmltools_0.5.1.1
    ## [22] Matrix_1.3-3        survey_4.0          psych_2.1.6
    ## [25] pcaPP_1.9-74        pkgconfig_2.0.3     ismev_1.42
    ## [28] purrr_0.3.4         GJRM_0.2-4          mvtnorm_1.1-2
    ## [31] scales_1.1.1        copula_1.0-1        tibble_3.1.2
    ## [34] ADGofTest_0.3       gmp_0.6-2           mgcv_1.8-36
    ## [37] generics_0.1.0      ggplot2_3.3.5       ellipsis_0.3.2
    ## [40] distrEx_2.8.0       Rmpfr_0.8-4         mnormt_2.0.2
    ## [43] survival_3.2-11     magrittr_2.0.1      crayon_1.4.1
    ## [46] evaluate_0.14       fansi_0.5.0         nlme_3.1-152
    ## [49] MASS_7.3-54         gsl_2.1-6           tools_4.1.0
    ## [52] mitools_2.4         lifecycle_1.0.0     pspline_1.0-18
    ## [55] matrixStats_0.59.0  stringr_1.4.0       trust_0.1-8
    ## [58] munsell_0.5.0       stabledist_0.7-1    scam_1.2-11
    ## [61] gamlss.dist_5.3-2   compiler_4.1.0      jquerylib_0.1.4
    ## [64] evd_2.3-3           rlang_0.4.11        grid_4.1.0
    ## [67] trustOptim_0.8.6.2  rmarkdown_2.9       gtable_0.3.0
    ## [70] abind_1.4-5         DBI_1.1.1           R6_2.5.0
    ## [73] knitr_1.33          dplyr_1.0.7         utf8_1.2.1
    ## [76] stringi_1.6.2       matrixcalc_1.0-4    parallel_4.1.0
    ## [79] Rcpp_1.0.6          vctrs_0.3.8         tidyselect_1.1.1
    ## [82] xfun_0.24

## References

- Fischer, R., Ferreira, M. C., Van Meurs, N. et al. (2019). “Does Organizational Formalization Facilitate Voice and Helping Organizational Citizenship Behaviors? It Depends on (National) Uncertainty Norms.” Journal of International Business Studies, 50(1), 125-134. https://doi.org/10.1057/s41267-017-0132-6

- Fischer, R., & Karl, J. A. (2019). “A Primer to (Cross-Cultural) Multi-Group Invariance Testing Possibilities in R.” Frontiers in psychology, 10, 1507. https://doi.org/10.3389/fpsyg.2019.01507

- Geminiani, E. (2020). “A Penalized Likelihood-Based Framework for Single and Multiple-Group Factor Analysis Models.” PhD thesis, University of Bologna. http://amsdottorato.unibo.it/9355/

- Geminiani, E., Marra, G., & Moustaki, I. (2021). “Single- and Multiple-Group Penalized Factor Analysis: A Trust-Region Algorithm Approach with Integrated Automatic Multiple Tuning Parameter Selection.” Psychometrika, 86(1), 65-95. https://doi.org/10.1007/s11336-021-09751-8