Skip to content

Commit d0b0294

Browse files
committed
lavaan_param_values(lav_fit, partable)
1 parent 72165da commit d0b0294

1 file changed

Lines changed: 142 additions & 0 deletions

File tree

src/frontend/specification/ParameterTable.jl

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,145 @@ values do not match.
374374
"""
375375
param_values(partable::ParameterTable, col::Symbol = :estimate) =
376376
param_values!(fill(NaN, nparams(partable)), partable, col)
377+
378+
"""
379+
lavaan_param_values!(out::AbstractVector, partable_lav,
380+
partable::ParameterTable,
381+
lav_col::Symbol = :est, lav_group = nothing)
382+
383+
Extract parameter values from the `partable_lav` lavaan model that
384+
match the parameters of `partable` into the `out` vector.
385+
386+
The method sets the *i*-th element of the `out` vector to
387+
the value of *i*-th parameter from `params(partable)`.
388+
389+
Note that the lavaan and `partable` models are matched by the
390+
the names of variables in the tables (`from` and `to` columns)
391+
as well as the type of their relationship (`relation` column),
392+
and not by the names of the model parameters.
393+
"""
394+
function lavaan_param_values!(
395+
out::AbstractVector,
396+
partable_lav,
397+
partable::ParameterTable,
398+
lav_col::Symbol = :est,
399+
lav_group = nothing,
400+
)
401+
402+
# find indices of all df row where f is true
403+
findallrows(f::Function, df) = findall(f(r) for r in eachrow(df))
404+
405+
(length(out) == nparams(partable)) || throw(
406+
DimensionMismatch(
407+
"The length of parameter values vector ($(length(out))) does not match the number of parameters ($(nparams(partable)))",
408+
),
409+
)
410+
partable_mask = findall(partable.columns[:free])
411+
param_index = Dict(param => i for (i, param) in enumerate(params(partable)))
412+
413+
lav_values = partable_lav[:, lav_col]
414+
for (from, to, type, id) in zip(
415+
[
416+
view(partable.columns[k], partable_mask) for
417+
k in [:from, :to, :parameter_type, :param]
418+
]...,
419+
)
420+
lav_ind = nothing
421+
422+
if from == Symbol("1")
423+
lav_ind = findallrows(
424+
r ->
425+
r[:lhs] == String(to) &&
426+
r[:op] == "~1" &&
427+
(isnothing(lav_group) || r[:group] == lav_group),
428+
partable_lav,
429+
)
430+
else
431+
if type == :
432+
lav_type = "~~"
433+
elseif type == :
434+
if (from partable.latent_vars) && (to partable.observed_vars)
435+
lav_type = "=~"
436+
else
437+
lav_type = "~"
438+
from, to = to, from
439+
end
440+
end
441+
442+
if lav_type == "~~"
443+
lav_ind = findallrows(
444+
r ->
445+
(
446+
(r[:lhs] == String(from) && r[:rhs] == String(to)) ||
447+
(r[:lhs] == String(to) && r[:rhs] == String(from))
448+
) &&
449+
r[:op] == lav_type &&
450+
(isnothing(lav_group) || r[:group] == lav_group),
451+
partable_lav,
452+
)
453+
else
454+
lav_ind = findallrows(
455+
r ->
456+
r[:lhs] == String(from) &&
457+
r[:rhs] == String(to) &&
458+
r[:op] == lav_type &&
459+
(isnothing(lav_group) || r[:group] == lav_group),
460+
partable_lav,
461+
)
462+
end
463+
end
464+
465+
if length(lav_ind) == 0
466+
throw(
467+
ErrorException(
468+
"Parameter $id ($from $type $to) could not be found in the lavaan solution",
469+
),
470+
)
471+
elseif length(lav_ind) > 1
472+
throw(
473+
ErrorException(
474+
"At least one parameter was found twice in the lavaan solution",
475+
),
476+
)
477+
end
478+
479+
param_ind = param_index[id]
480+
param_val = lav_values[lav_ind[1]]
481+
if isnan(out[param_ind])
482+
out[param_ind] = param_val
483+
else
484+
@assert out[param_ind] param_val atol = 1E-10 "Parameter :$id value at row #$lav_ind ($param_val) differs from the earlier encountered value ($(out[param_ind]))"
485+
end
486+
end
487+
488+
return out
489+
end
490+
491+
"""
492+
lavaan_param_values(partable_lav, partable::ParameterTable,
493+
lav_col::Symbol = :est, lav_group = nothing)
494+
495+
Extract parameter values from the `partable_lav` lavaan model that
496+
match the parameters of `partable`.
497+
498+
The `out` vector should be of `nparams(partable)` length.
499+
The *i*-th element of the `out` vector will contain the
500+
value of the *i*-th parameter from `params(partable)`.
501+
502+
Note that the lavaan and `partable` models are matched by the
503+
the names of variables in the tables (`from` and `to` columns),
504+
and the type of their relationship (`relation` column),
505+
but not by the ids of the model parameters.
506+
"""
507+
lavaan_param_values(
508+
partable_lav,
509+
partable::ParameterTable,
510+
lav_col::Symbol = :est,
511+
lav_group = nothing,
512+
) = lavaan_param_values!(
513+
fill(NaN, nparams(partable)),
514+
partable_lav,
515+
partable,
516+
lav_col,
517+
lav_group,
518+
)

0 commit comments

Comments
 (0)