The lasars package provides tools for estimating latent states and response styles from Likert-scale survey data. By explicitly modelling response tendencies, the package separates response behaviour from substantive latent-state estimates. This can reduce bias in survey scores and provide insight into individual differences in responding.
This vignette introduces the basic lasars workflow using the default Particle Metropolis within Gibbs (PMwG) estimation method and briefly describes alternative modelling options available in the package.
example_lasars_data contains responses from 10
participants who completed a 50-item International Personality Item Pool
(IPIP) questionnaire. The data include positively and negatively worded
items and are therefore well suited for demonstrating response-style
estimation.
To fit a lasars model we provide:
It is generally recommended to estimate a Directional Preference
parameter where the data allows (with a reasonable number of
reverse-coded items throughout) because this captures a wider range of
response behaviours. When estimating the Directional Preference
parameter (est_directPref = TRUE), users must provide
additional information identifying reverse-coded items.
Additional PMwG (the default sampling method) settings, such as
iterations and particles, may also be
supplied, along with user-defined priors. Although sensible defaults are
provided, we use smaller values in this vignette to reduce computation
time. For substantive analyses, larger values are generally recommended
to ensure adequate sampling. Note: These settings will generate a
warning that the PMwG sampler did not finish adaptation phase early;
this is fine for these demonstration purposes but you should revise
iteration and/or particle settings if this error is received during
analysis.
result <- run_lasars(data = example_lasars_data,
resp_opts = 5,
est_directPref = TRUE,
subject_colname = "subject",
response_colname = "response",
latentState_colname = "subscale",
direction_colname = "reverse",
rev_score_id = 'TRUE',
iterations = 100, #Optional - speed up vignette
particles = 15 #Optional - speed up vignette
)
#> MESSAGE: Sampling Initial values for random effects
#> | | | 0% | |= | 2% | |=== | 4% | |==== | 6% | |====== | 8% | |======= | 10% | |======== | 12% | |========== | 14% | |=========== | 16% | |============= | 18% | |============== | 20% | |=============== | 22% | |================= | 24% | |================== | 26% | |==================== | 28% | |===================== | 30% | |====================== | 32% | |======================== | 34% | |========================= | 36% | |=========================== | 38% | |============================ | 40% | |============================= | 42% | |=============================== | 44% | |================================ | 46% | |================================== | 48% | |=================================== | 50% | |==================================== | 52% | |====================================== | 54% | |======================================= | 56% | |========================================= | 58% | |========================================== | 60% | |=========================================== | 62% | |============================================= | 64% | |============================================== | 66% | |================================================ | 68% | |================================================= | 70% | |================================================== | 72% | |==================================================== | 74% | |===================================================== | 76% | |======================================================= | 78% | |======================================================== | 80% | |========================================================= | 82% | |=========================================================== | 84% | |============================================================ | 86% | |============================================================== | 88% | |=============================================================== | 90% | |================================================================ | 92% | |================================================================== | 94% | |=================================================================== | 96% | |===================================================================== | 98% | |======================================================================| 100%
#> MESSAGE: Epsilon has been set to 0.5 based on number of parameters
#> MESSAGE: mix has been set to c(0.5, 0.5, 0) based on the stage being run
#> Phase 1: Burn in
#> | | 0% | New( 0%) |= | 1% | New( 0%) |= | 2% | New( 0%) |== | 3% | New(100%) |== | 4% | New(100%) |=== | 5% | New(100%) |==== | 6% | New(100%) |==== | 7% | New(100%) |===== | 8% | New(100%) |===== | 9% | New(100%) |====== | 10% | New(100%) |======= | 11% | New(100%) |======= | 12% | New(100%) |======== | 13% | New(100%) |======== | 14% | New(100%) |========= | 15% | New(100%) |========== | 16% | New(100%) |========== | 17% | New(100%) |=========== | 18% | New(100%) |=========== | 19% | New(100%) |============ | 20% | New(100%) |============= | 21% | New(100%) |============= | 22% | New(100%) |============== | 23% | New(100%) |============== | 24% | New(100%) |=============== | 25% | New(100%) |================ | 26% | New(100%) |================ | 27% | New(100%) |================= | 28% | New( 99%) |================= | 29% | New( 99%) |================== | 30% | New( 99%) |=================== | 31% | New( 99%) |=================== | 32% | New( 99%) |==================== | 33% | New( 99%) |==================== | 34% | New( 99%) |===================== | 35% | New( 99%) |====================== | 36% | New( 99%) |====================== | 37% | New(100%) |======================= | 38% | New(100%) |======================= | 39% | New(100%) |======================== | 40% | New( 99%) |========================= | 41% | New( 99%) |========================= | 42% | New( 99%) |========================== | 43% | New( 99%) |========================== | 44% | New( 99%) |=========================== | 45% | New( 99%) |============================ | 46% | New( 99%) |============================ | 47% | New( 99%) |============================= | 48% | New( 99%) |============================= | 49% | New( 99%) |============================== | 50% | New( 99%) |=============================== | 51% | New( 99%) |=============================== | 52% | New( 99%) |================================ | 53% | New( 99%) |================================ | 54% | New( 99%) |================================= | 55% | New( 99%) |================================== | 56% | New( 99%) |================================== | 57% | New( 99%) |=================================== | 58% | New( 99%) |=================================== | 59% | New( 99%) |==================================== | 60% | New( 99%) |===================================== | 61% | New( 99%) |===================================== | 62% | New( 99%) |====================================== | 63% | New( 99%) |====================================== | 64% | New( 99%) |======================================= | 65% | New( 99%) |======================================== | 66% | New( 99%) |======================================== | 67% | New( 99%) |========================================= | 68% | New( 99%) |========================================= | 69% | New( 99%) |========================================== | 70% | New( 99%) |=========================================== | 71% | New( 99%) |=========================================== | 72% | New( 99%) |============================================ | 73% | New( 99%) |============================================ | 74% | New( 99%) |============================================= | 75% | New( 99%) |============================================== | 76% | New( 99%) |============================================== | 77% | New( 99%) |=============================================== | 78% | New( 99%) |=============================================== | 79% | New( 99%) |================================================ | 80% | New( 99%) |================================================= | 81% | New( 99%) |================================================= | 82% | New( 99%) |================================================== | 83% | New( 99%) |================================================== | 84% | New( 99%) |=================================================== | 85% | New( 99%) |==================================================== | 86% | New( 98%) |==================================================== | 87% | New( 98%) |===================================================== | 88% | New( 98%) |===================================================== | 89% | New( 98%) |====================================================== | 90% | New( 98%) |======================================================= | 91% | New( 98%) |======================================================= | 92% | New( 98%) |======================================================== | 93% | New( 98%) |======================================================== | 94% | New( 98%) |========================================================= | 95% | New( 98%) |========================================================== | 96% | New( 98%) |========================================================== | 97% | New( 98%) |=========================================================== | 98% | New( 98%) |=========================================================== | 99% | New( 98%) |============================================================| 100% | New( 97%)
#> MESSAGE: mix has been set to c(0.5, 0.5, 0) based on the stage being run
#> Phase 2: Adaptation
#> | | 0% | New( 0%) |= | 1% | New( 97%) |= | 2% | New( 97%) |== | 3% | New( 97%) |== | 4% | New( 97%) |=== | 5% | New( 97%) |==== | 6% | New( 97%) |==== | 7% | New( 97%) |===== | 8% | New( 97%) |===== | 9% | New( 97%) |====== | 10% | New( 97%) |======= | 11% | New( 97%) |======= | 12% | New( 97%) |======== | 13% | New( 97%) |======== | 14% | New( 97%) |========= | 15% | New( 97%) |========== | 16% | New( 96%) |========== | 17% | New( 96%) |=========== | 18% | New( 96%) |=========== | 19% | New( 96%) |============ | 20% | New( 96%) |============= | 21% | New( 96%) |============= | 22% | New( 96%) |============== | 23% | New( 96%) |============== | 24% | New( 96%) |=============== | 25% | New( 96%) |================ | 26% | New( 96%) |================ | 27% | New( 96%) |================= | 28% | New( 96%) |================= | 29% | New( 95%) |================== | 30% | New( 95%) |=================== | 31% | New( 95%) |=================== | 32% | New( 95%) |==================== | 33% | New( 95%) |==================== | 34% | New( 95%) |===================== | 35% | New( 95%) |====================== | 36% | New( 95%) |====================== | 37% | New( 95%) |======================= | 38% | New( 95%) |======================= | 39% | New( 95%) |======================== | 40% | New( 95%) |========================= | 41% | New( 95%) |========================= | 42% | New( 94%) |========================== | 43% | New( 94%) |========================== | 44% | New( 94%) |=========================== | 45% | New( 94%) |============================ | 46% | New( 94%) |============================ | 47% | New( 94%) |============================= | 48% | New( 94%) |============================= | 49% | New( 94%) |============================== | 50% | New( 94%) |=============================== | 51% | New( 93%) |=============================== | 52% | New( 93%) |================================ | 53% | New( 93%) |================================ | 54% | New( 93%) |================================= | 55% | New( 93%) |================================== | 56% | New( 93%) |================================== | 57% | New( 93%) |=================================== | 58% | New( 93%) |=================================== | 59% | New( 93%) |==================================== | 60% | New( 93%) |===================================== | 61% | New( 92%) |===================================== | 62% | New( 92%) |====================================== | 63% | New( 92%) |====================================== | 64% | New( 92%) |======================================= | 65% | New( 92%) |======================================== | 66% | New( 92%) |======================================== | 67% | New( 92%) |========================================= | 68% | New( 92%) |========================================= | 69% | New( 92%) |========================================== | 70% | New( 91%) |=========================================== | 71% | New( 91%) |=========================================== | 72% | New( 91%) |============================================ | 73% | New( 91%) |============================================ | 74% | New( 91%) |============================================= | 75% | New( 91%) |============================================== | 76% | New( 91%) |============================================== | 77% | New( 91%) |=============================================== | 78% | New( 90%) |=============================================== | 79% | New( 90%) |================================================ | 80% | New( 90%) |================================================= | 81% | New( 90%) |================================================= | 82% | New( 90%) |================================================== | 83% | New( 90%) |================================================== | 84% | New( 90%) |=================================================== | 85% | New( 90%) |==================================================== | 86% | New( 90%) |==================================================== | 87% | New( 90%) |===================================================== | 88% | New( 90%) |===================================================== | 89% | New( 90%) |====================================================== | 90% | New( 90%) |======================================================= | 91% | New( 90%) |======================================================= | 92% | New( 90%) |======================================================== | 93% | New( 90%) |======================================================== | 94% | New( 90%) |========================================================= | 95% | New( 90%) |========================================================== | 96% | New( 90%) |========================================================== | 97% | New( 90%) |=========================================================== | 98% | New( 90%) |=========================================================== | 99% | New( 90%) |============================================================| 100% | New( 89%)
#> WARNING: Particle Metropolis within Gibbs Sampler did not finish adaptation phase early (all 100 iterations were run).
#> You should examine your samples and perhaps start a longer adaptation run.
#> MESSAGE: mix has been set to c(0.1, 0.2, 0.7) based on the stage being run
#> Phase 3: Sampling
#> | | 0% | New( 0%) |= | 1% | New( 89%) |= | 2% | New( 89%) |== | 3% | New( 89%) |== | 4% | New( 89%) |=== | 5% | New( 89%) |==== | 6% | New( 89%) |==== | 7% | New( 89%) |===== | 8% | New( 89%) |===== | 9% | New( 88%) |====== | 10% | New( 88%) |======= | 11% | New( 88%) |======= | 12% | New( 88%) |======== | 13% | New( 88%) |======== | 14% | New( 88%) |========= | 15% | New( 88%) |========== | 16% | New( 88%) |========== | 17% | New( 87%) |=========== | 18% | New( 87%) |=========== | 19% | New( 87%) |============ | 20% | New( 87%) |============= | 21% | New( 87%) |============= | 22% | New( 87%) |============== | 23% | New( 87%) |============== | 24% | New( 86%) |=============== | 25% | New( 86%) |================ | 26% | New( 86%) |================ | 27% | New( 86%) |================= | 28% | New( 86%) |================= | 29% | New( 86%) |================== | 30% | New( 86%) |=================== | 31% | New( 86%) |=================== | 32% | New( 86%) |==================== | 33% | New( 85%) |==================== | 34% | New( 85%) |===================== | 35% | New( 85%) |====================== | 36% | New( 85%) |====================== | 37% | New( 85%) |======================= | 38% | New( 85%) |======================= | 39% | New( 85%) |======================== | 40% | New( 84%) |========================= | 41% | New( 84%) |========================= | 42% | New( 84%) |========================== | 43% | New( 84%) |========================== | 44% | New( 84%) |=========================== | 45% | New( 84%) |============================ | 46% | New( 84%) |============================ | 47% | New( 84%) |============================= | 48% | New( 84%) |============================= | 49% | New( 83%) |============================== | 50% | New( 83%) |=============================== | 51% | New( 83%) |=============================== | 52% | New( 83%) |================================ | 53% | New( 83%) |================================ | 54% | New( 83%) |================================= | 55% | New( 83%) |================================== | 56% | New( 83%) |================================== | 57% | New( 83%) |=================================== | 58% | New( 83%) |=================================== | 59% | New( 83%) |==================================== | 60% | New( 83%) |===================================== | 61% | New( 83%) |===================================== | 62% | New( 83%) |====================================== | 63% | New( 83%) |====================================== | 64% | New( 83%) |======================================= | 65% | New( 83%) |======================================== | 66% | New( 82%) |======================================== | 67% | New( 82%) |========================================= | 68% | New( 82%) |========================================= | 69% | New( 82%) |========================================== | 70% | New( 82%) |=========================================== | 71% | New( 82%) |=========================================== | 72% | New( 82%) |============================================ | 73% | New( 82%) |============================================ | 74% | New( 82%) |============================================= | 75% | New( 82%) |============================================== | 76% | New( 81%) |============================================== | 77% | New( 81%) |=============================================== | 78% | New( 81%) |=============================================== | 79% | New( 81%) |================================================ | 80% | New( 81%) |================================================= | 81% | New( 81%) |================================================= | 82% | New( 81%) |================================================== | 83% | New( 81%) |================================================== | 84% | New( 81%) |=================================================== | 85% | New( 81%) |==================================================== | 86% | New( 81%) |==================================================== | 87% | New( 81%) |===================================================== | 88% | New( 81%) |===================================================== | 89% | New( 81%) |====================================================== | 90% | New( 81%) |======================================================= | 91% | New( 80%) |======================================================= | 92% | New( 80%) |======================================================== | 93% | New( 80%) |======================================================== | 94% | New( 80%) |========================================================= | 95% | New( 80%) |========================================================== | 96% | New( 80%) |========================================================== | 97% | New( 80%) |=========================================================== | 98% | New( 80%) |=========================================================== | 99% | New( 80%) |============================================================| 100% | New( 80%)The PMwG object contains posterior samples at multiple levels: - alpha contains subject-level parameter estimates. - theta_mu contains group-level means. - theta_sig contains estimated covariance matrices.
These posterior distributions can be summarised using posterior means, medians, credible intervals, or other Bayesian summary statistics.
It is also possible to set sampling_method = 'mle',
which overrides the default PMwG sampling method in favour of a simpler
maximum-likelihood method.
mle_result <- run_lasars(data = example_lasars_data,
resp_opts = 5,
est_directPref = TRUE,
subject_colname = "subject",
response_colname = "response",
latentState_colname = "subscale",
direction_colname = "reverse",
rev_score_id = 'TRUE',
sampling_method = 'mle')
head(mle_result)
#> subject mu.extra mu.neuro mu.agree mu.consc mu.open centrePref oddsPref
#> 44 44 0.216 0.280 1.777 -0.102 0.223 -0.597 -0.738
#> 355 355 0.840 0.063 6.608 0.792 1.251 -0.370 -0.453
#> 473 473 -2.441 2.081 0.496 1.015 0.595 0.211 -0.638
#> 4082 4082 -1.653 1.237 2.355 0.072 1.990 0.573 -0.775
#> 5053 5053 -1.272 -1.311 0.953 0.953 0.253 0.388 -0.650
#> 5758 5758 0.228 -0.901 0.358 1.716 2.297 -0.041 -0.014
#> directionPref convergence
#> 44 -0.274 Success
#> 355 0.171 Success
#> 473 -0.071 Success
#> 4082 -0.381 Success
#> 5053 0.034 Success
#> 5758 -0.140 SuccessWhile this allows for much faster sampling, it no longer allows for the advantages of the hierarchical Bayesian PMwG approach. This means the sampling result is a data frame with a single estimate for each parameter for each person. In this way, the output may be simpler to interpret, but it does not include a posterior distribution which allows for uncertainty in parameter estimates to be quantified through credible intervals and posterior summaries.
run_latstat())A second analysis is also included in this package - the latstat model, which estimates only latent state parameters. This model adopts the approach described in Grimmond et al. (2025), whereby response style is captured through the estimation of absolute threshold values making response style difficult to interpret in a psychologically meaningful way. Given the difficulty in interpreting the Odds Preference parameter for surveys with more than 5 response options, the latstat model may provide greater flexibility for latent-state estimation and be preferred in applications to larger response formats.
The latstat analysis takes the same input parameters as the lasars
model, except the est_directPref parameter, and always
requires the direction_colname and
rev_score_id parameters. As with the lasars analysis, the
default sampling_method is PMwG, but an ‘mle’ option is
available.
The default lasars model is recommended when: - response-style estimates are of substantive interest - reverse-coded items are limited or absent - surveys contain five or fewer response options
The latstat model may be preferable when: - latent-state estimation is the only goal - surveys contain six or more response options - reverse-coded items are present
There are three other functions in the lasars package which users may choose to use. Though none of these are necessary, they allow the user extra control of model settings, sampling methodology and allow for easy model-fit assessment.
The first is the make_priors() which does what it says
on the tin: it allows the user to make a prior object appropriate for
PMwG estimation based on the shape of the input data frame. This takes a
data frame, the number of response options and the latent state column
name as required inputs. If the analysis = "lasars" (which
is the default), an est_directPref parameter will also be
required. The function will then take additional inputs for different
prior values, allowing users to set their own informative priors where
necessary
test_priors <- make_priors(data = example_lasars_data,
resp_opts = 5,
latentState_colname = "subscale",
est_directPref = TRUE,
mu_prior = 0.5,
centrePref_prior = 0.3)
test_priors
#> $theta_mu_mean
#> mu.extra mu.neuro mu.agree mu.consc mu.open
#> 0.5 0.5 0.5 0.5 0.5
#> centrePref oddsPref directionPref
#> 0.3 0.0 0.0
#>
#> $theta_mu_var
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,] 1 0 0 0 0 0 0 0
#> [2,] 0 1 0 0 0 0 0 0
#> [3,] 0 0 1 0 0 0 0 0
#> [4,] 0 0 0 1 0 0 0 0
#> [5,] 0 0 0 0 1 0 0 0
#> [6,] 0 0 0 0 0 1 0 0
#> [7,] 0 0 0 0 0 0 1 0
#> [8,] 0 0 0 0 0 0 0 1The output of the make_priors() function can then be
passed into the run_lasars() or run_latstat()
functions to allow for more flexibility with prior settings.
testing_priors_result <- run_lasars(data = example_lasars_data,
resp_opts = 5,
est_directPref = TRUE,
subject_colname = "subject",
response_colname = "response",
latentState_colname = "subscale",
direction_colname = "reverse",
rev_score_id = 'TRUE',
priors = test_priors)The package also contains the likelihood functions for both analyses:
lasars_ll_func() and latstat_ll_func(). If
model users wish to apply these methods outside of the PMwG or
maximum-likelihood frameworks provided in this package, these likelihood
functions can be used or adapted as necessary.
Finally, the gen_pp_data() function generates simulated
data, based on estimated parameter values, allowing for model-fit to be
assessed. If the sampled object is a PMwG object, the information about
the likelihood function and original data structure to be emulated are
already contained within the results object. When
sampling_method = 'mle', additional parameter inputs are
necessary, including the likelihood function used and the original data
frame the model was fit to. The default is to generate 20 sets of
simulated data which will take the same form as the observed data
frame.
pp_data <- gen_pp_data(sampled = result)
#> subject 1
#> subject 2
#> subject 3
#> subject 4
#> subject 5
#> subject 6
#> subject 7
#> subject 8
#> subject 9
#> subject 10
#> subject 11
#> subject 12
#> subject 13
#> subject 14
#> subject 15
#> subject 16
#> subject 17
#> subject 18
#> subject 19
#> subject 20
#> subject 21
#> subject 22
#> subject 23
#> subject 24
#> subject 25
#> subject 26
#> subject 27
#> subject 28
#> subject 29
#> subject 30
#> subject 31
#> subject 32
#> subject 33
#> subject 34
#> subject 35
#> subject 36
#> subject 37
#> subject 38
#> subject 39
#> subject 40
#> subject 41
#> subject 42
#> subject 43
#> subject 44
#> subject 45
#> subject 46
#> subject 47
#> subject 48
#> subject 49
#> subject 50
head(pp_data)
#> subject item response subscale reverse iter
#> 2 44 EXT2 1 extra TRUE 1
#> 3 44 EXT3 1 extra FALSE 1
#> 4 44 EXT4 3 extra TRUE 1
#> 5 44 EXT5 5 extra FALSE 1
#> 6 44 EXT6 1 extra TRUE 1
#> 7 44 EXT7 5 extra FALSE 1Grimmond, J., Brown, S. D., & Hawkins, G. E. (2025). A solution to the pervasive problem of response bias in self-reports. Proceedings of the National Academy of Sciences, 122(3), e2412807122.
#> R version 4.5.3 (2026-03-11 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#>
#> Matrix products: default
#> LAPACK version 3.12.1
#>
#> locale:
#> [1] LC_COLLATE=C LC_CTYPE=English_Australia.utf8
#> [3] LC_MONETARY=English_Australia.utf8 LC_NUMERIC=C
#> [5] LC_TIME=English_Australia.utf8
#>
#> time zone: Australia/Sydney
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] lasars_0.1.1
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.7.3 cli_3.6.6 knitr_1.51 rlang_1.3.0
#> [5] xfun_0.59 otel_0.2.0 condMVNorm_2025.1 purrr_1.2.2
#> [9] jsonlite_2.0.0 pmwg_0.2.7 backports_1.5.1 htmltools_0.5.9
#> [13] sass_0.4.10 rmarkdown_2.31 evaluate_1.0.5 jquerylib_0.1.4
#> [17] MASS_7.3-65 fastmap_1.2.0 yaml_2.3.12 mvtnorm_1.4-1
#> [21] lifecycle_1.0.5 compiler_4.5.3 rstudioapi_0.18.0 digest_0.6.39
#> [25] R6_2.6.1 magrittr_2.0.5 bslib_0.11.0 checkmate_2.3.4
#> [29] tools_4.5.3 cachem_1.1.0