Help us shape the future of Go! Take the 2026 Go Developer Survey

sem

package
v1.0.0-alpha.34 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package sem is the structural equation model (SEM) estimator behind MAT_SEM: a lavaan / semopy model description fitted by maximum likelihood to a sample covariance matrix.

Its default setup is semopy 2.3.11's default covariance-structure model (semopy.Model, obj="MLW", solver="SLSQP", mimic_lavaan=False): the same variable classification, parameter set and fixings, the same Wishart ML objective minimised by SciPy's SLSQP (package optimize) with semopy's settings, the same expected-information standard errors and the same fit statistics — so a fit over the same data gives semopy's numbers, its early stop at ftol included. Options select a converging Fisher-scoring solver and the rank-2 derivative computation instead.

A mean structure (ModelOptions.MeanStructure, or a `~ 1` statement) is a lavaan-only feature: the model gains intercepts and latent means, and the fit follows lavaan's conventions instead (Model.Lavaan: Fisher scoring to the optimum, unbounded variances, lavaan's statistics and Wald intervals), reproducing lavaan's ML fit.

The package reads only a covariance matrix and a row count (and the sample means under a mean structure); it is no-execute safe (stdlib, gonum) and imported by both the resolver (internal/vectors: model validation at predict time) and the engine (internal/processing: the finalizer).

Index

Constants

View Source
const (
	DefinedReasonSyntax       = "syntax"
	DefinedReasonUnknownLabel = "unknown_label"
	DefinedReasonForwardRef   = "forward_reference"
	DefinedReasonDuplicate    = "duplicate"
)

Defined-parameter refusal reasons (DefinedError.Reason).

View Source
const (
	OrdinalSpecNotObserved = "not_observed"
	OrdinalSpecNotOutput   = "not_output"
	OrdinalSpecExogenous   = "exogenous_observed"
	OrdinalSpecIntercept   = "ordered_intercept"
	OrdinalSpecVariance    = "ordered_variance"
)

Reasons of an OrdinalSpecError.

View Source
const (
	PolychoricBound = 0.999
	PolyserialBound = 0.995
)

Bounds of the bivariate estimates (lavaan's nlminb boxes): the polychoric and Pearson searches stay in ±0.999, the polyserial in ±0.995. A maximum outside the box is reported on its edge (PairEstimate.Bound).

View Source
const (
	// ReasonNoData: no row, or a total weight that is not positive.
	ReasonNoData = "no_data"
	// ReasonInvalidInput: a ragged row, a non-finite value, a code
	// outside 0..Levels-1, a negative or non-finite weight, or a kind /
	// level spec that does not describe the columns.
	ReasonInvalidInput = "invalid_input"
	// ReasonConstant: a variable without spread — an ordered one with a
	// single category (Levels 1, or every weight on one code), a numeric
	// one with zero variance.
	ReasonConstant = "constant"
	// ReasonEmptyCategory: an ordered variable with a declared category
	// no row (no positive weight) falls in — the lavaan refusal "some
	// categories of variable are empty in group g", reached when a
	// category observed in the pooled data is missing from one group.
	ReasonEmptyCategory = "empty_category"
	// ReasonTooManyCategories: an ordered variable declaring more than
	// MaxOrderedCategories categories (Levels) — one threshold per
	// category boundary and a Γ of matching size, so a high-cardinality
	// numeric column declared ordered is refused, never fitted.
	ReasonTooManyCategories = "too_many_categories"
)

Reasons of an OrdinalError.

View Source
const (
	OpRegression  = "~"
	OpMeasurement = "=~"
	OpCovariance  = "~~"
	// OpIntercept is a "~ 1" term: an observed variable's intercept or
	// a latent variable's mean (lavaan's mean-structure syntax). It
	// switches the fit to lavaan conventions (Model.Lavaan).
	OpIntercept = "~1"
	// OpThreshold is an ordered variable's threshold row ("x | t1"):
	// never model syntax, only an ordinal fit's estimates (FitOrdinal).
	OpThreshold = "|"
	// OpScale is an ordered variable's scale-factor row ("x ~*~ x",
	// the delta parameterization's Δ): never model syntax, only a
	// multi-group ordinal fit's estimates (FitOrdinalGroups).
	OpScale = "~*~"
)

Operators of the model syntax.

View Source
const BootstrapMinSuccesses = 10

BootstrapMinSuccesses is the fewest successful replicates a bootstrap reports from.

View Source
const GroupEqualThresholds = "thresholds"

GroupEqualThresholds is the group_equal value holding every ordered variable's thresholds equal across groups (an ordinal fit only).

View Source
const MaxOrderedCategories = 32

MaxOrderedCategories is the most categories one ordered variable may declare (Levels; MaxOrderedCategories − 1 thresholds). A rating scale sits far below it — a 0–10 scale has 11, and lavaan already warns above 12 — so a column past it is a continuous measure declared ordered by mistake: its thresholds and Γ (rows and columns per threshold, per group) would grow with its distinct values.

View Source
const NearestThreshold = 1e-2

NearestThreshold is the eigenvalue floor semopy passes to cov_nearest.

View Source
const OpDefined = ":="

OpDefined is a defined parameter's estimate-row operator: lavaan's ":=". The row's LVal is the name, RVal the expression without whitespace (lavaan's rhs).

View Source
const ReasonSingular = "singular"

ReasonSingular is an OrdinalError reason: the asymptotic covariance is undefined — a univariate information block or a correlation's information does not invert, or a figure is not finite (a correlation at ±1).

Variables

View Source
var ErrEBMResidualVariance = errors.New("a residual variance is not positive; ordinal (EBM) factor scores are undefined")

ErrEBMResidualVariance refuses EBM scores of a fit with a residual variance (an ordered indicator's delta residual, a numeric indicator's Θ_ii) that is not positive: the indicator's density is undefined (lavaan refuses the same).

View Source
var ErrScoreSingular = errors.New("the fit's implied covariance is singular; factor scores need its inverse")

ErrScoreSingular reports a fit whose scores are undefined: the implied covariance (or Bartlett's ΛᵀΣ⁻¹Λ) cannot be inverted.

Functions

func BivariateNormalCDF

func BivariateNormalCDF(h, k, r float64) float64

BivariateNormalCDF is P(X ≤ h, Y ≤ k) for a standard bivariate normal pair with correlation r (pbivnorm(h, k, r)). An infinite limit reduces exactly to the univariate CDF (or 0); |r| > 1 or a NaN argument is NaN.

func ComputeStats

func ComputeStats(fit *Fit, desc string) error

ComputeStats fills fit.Stats; desc is the model description, used to fit semopy's baseline (independence) model on the same covariance. A lavaan-convention fit (Model.Lavaan) gets lavaan's figures instead (lavaanStats); desc is then unused.

func GroupEqualValues

func GroupEqualValues() []string

GroupEqualValues are the accepted group_equal values, lavaan's group.equal vocabulary (thresholds needs an ordinal estimator).

func GroupFreeRows

func GroupFreeRows(model *Model, levels int) (int, error)

GroupFreeRows is how many parameter-table rows carry a free parameter across a multi-group fit of model (NewGroupModel) over levels groups (the first the reference): every group's free rows, the specification's non-reference freeing and equality fixing applied. The rows a member multiplicity block corrects, less the := rows.

func HasDefined

func HasDefined(desc string) bool

HasDefined reports whether a description parses and carries any := line — a defined parameter, so lavaan conventions.

func HasGroupModifiers

func HasGroupModifiers(desc string) bool

HasGroupModifiers reports whether a description parses and carries any per-group modifier c(...) — a multi-group construct.

func HasIntercepts

func HasIntercepts(desc string) bool

HasIntercepts reports whether a description parses and carries any `~ 1` statement — a mean structure, so lavaan conventions.

func PositiveDefinite

func PositiveDefinite(s *mat.SymDense) bool

PositiveDefinite reports whether s factors by Cholesky — the test semopy's load_cov applies (LAPACK dpotrf) before falling back to CovNearest.

func ScoreMethods

func ScoreMethods() []string

ScoreMethods returns the methods, default first.

func ThresholdScores

func ThresholdScores(th []float64, c int, out []float64)

ThresholdScores writes the casewise threshold scores of one row in category c (lav_uvord_sc: ∂ log π_c / ∂τ_k, two non-zero entries — the category's upper threshold +φ(τ_c)/π_c, its lower −φ(τ_{c−1})/π_c) into out (len(th) values).

Types

type Bootstrap

type Bootstrap struct {
	Requested, Succeeded int
	SE, CILower, CIUpper []float64
}

Bootstrap is a bootstrap's per-row figures, index-aligned with the full fit's table rows (BootstrapRows): SE and the percentile bounds, NaN on a row Apply leaves alone.

func RunBootstrap

func RunBootstrap(m *Model, samples []BootstrapSample, opt Options, bo BootstrapOptions, full []Estimate) (*Bootstrap, error)

RunBootstrap bootstraps the fit whose table rows are full (BootstrapRows / BootstrapGroupRows): one sample is a single-group fit (FitMoments), two or more a multi-group fit (FitGroups) of m, every replicate with opt. A replicate's moments are its rows' mean and biased (divisor n) covariance, as the full fit's.

func (*Bootstrap) Apply

func (b *Bootstrap) Apply(rows []Estimate)

Apply writes b's figures into rows (the table rows b was run on): every bootstrapped row takes its SE, z = value / SE, p and the percentile interval; any other row is left as is.

type BootstrapError

type BootstrapError struct {
	Requested, Attempted, Succeeded int
}

BootstrapError is a bootstrap with fewer than BootstrapMinSuccesses successful replicates: Attempted replicates ran (fewer than Requested after the early stop) and Succeeded of them refitted.

func (*BootstrapError) Error

func (e *BootstrapError) Error() string

type BootstrapOptions

type BootstrapOptions struct {
	// Iters is the replicate count B (positive).
	Iters int
	// Seed seeds the replicate draws.
	Seed uint64
	// Level is the percentile interval's level, in (0, 1).
	Level float64
	// Standardize fits every replicate to its rows z-scored with the
	// population SD — the correlation matrix and zero means — as the
	// full fit of a standardizing vector is.
	Standardize bool
	// Ctx, when non-nil, is read before every replicate: a deadline or a
	// cancel stops the bootstrap between two refits with ctx's own
	// error.
	Ctx context.Context
	// Ordinal, when non-nil, refits every replicate by an ordinal
	// estimator (FitOrdinal, or FitOrdinalGroups over two or more
	// samples) from the replicate's own two-step statistics: the
	// samples' rows hold the category codes of the full fit's coding,
	// which every replicate keeps, so a replicate that loses a category
	// (in any group) fails and is skipped — lavaan's bootstrap of a
	// categorical fit.
	Ordinal *BootstrapOrdinal
}

BootstrapOptions configure Bootstrap.

type BootstrapOrdinal

type BootstrapOrdinal struct {
	Estimator Estimator
	Kinds     []OrdinalKind
	Levels    []int
}

BootstrapOrdinal is an ordinal bootstrap's refit: the estimator and the full fit's column kinds and category counts.

type BootstrapSample

type BootstrapSample struct {
	Rows      []float64
	Label     string
	Level     int
	Reference bool
}

BootstrapSample is one group's rows for resampling: row-major over the model's Observed order (len(Rows) a multiple of len(Observed)), plus the group's place in a multi-group fit (GroupMoments' Label, Level and Reference; ignored on a single-group fit).

type ConstraintError

type ConstraintError struct {
	Op, Line string
}

ConstraintError is a refused lavaan constraint line (==, <, >): only equality through shared labels is supported. Op is the operator.

func (*ConstraintError) Error

func (e *ConstraintError) Error() string

type DefinedError

type DefinedError struct {
	Name, Reason, Ref, Msg string
}

DefinedError is a refused := line: Name the defined parameter ("" when the line has none), Reason one of the DefinedReason* values and Ref the offending reference (unknown_label, forward_reference).

func (*DefinedError) Error

func (e *DefinedError) Error() string

type EBMScorer

type EBMScorer struct {
	// contains filtered or unexported fields
}

EBMScorer is one group's EBM scoring rule (NewEBMScorer).

func NewEBMScorer

func NewEBMScorer(m *Model, p Params, latent string) (*EBMScorer, error)

NewEBMScorer builds the EBM rule of latent from one group's parameters p of the ordinal model m (ModelOptions.Ordered; p carries the thresholds, Params.Thresholds). An observed inner variable is a dummy latent (the file comment); ErrScoreSingular when the latents' implied covariance is not positive definite; ErrEBMResidualVariance for a non-positive residual variance (an observed inner variable's Ψ_dd included).

func (*EBMScorer) Mode

func (s *EBMScorer) Mode(y, eta []float64) int

Mode writes the posterior mode of every latent (Inner order) for the row y into eta and returns the Newton steps taken.

func (*EBMScorer) Score

func (s *EBMScorer) Score(y []float64) float64

Score is the row's score on the scorer's latent: the posterior mode's coordinate (Mode). y is over Observed, every value present: an ordered indicator's category code (0 the lowest category), a numeric indicator's value.

type Effects

type Effects struct {
	// contains filtered or unexported fields
}

Effects maps operator -> left variable -> right variable -> multiplier, keeping first-seen order at every level (semopy iterates dicts in insertion order, which fixes its parameter order).

func Parse

func Parse(desc string) (*Effects, error)

Parse reads a model description in semopy / lavaan syntax: one statement per line, `#` comments, `=~` (measurement), `~` (regression) and `~~` (covariance), comma-separated left sides, `+`-separated right sides and optional `mult*` prefixes (a number, a label, NA, or lavaan's per-group list c(m1, m2, ...)). A `1` term on a `~` right side (`x ~ 1`, `x ~ 0*1`, `x ~ a*1`, `y ~ 1 + x`) is an intercept / latent mean, kept under OpIntercept. A `name := expr` line is a defined parameter (defined.go); a lavaan constraint line (==, <, >) is a *ConstraintError. semopy's operation commands (START, BOUND, DEFINE, ...) are not supported.

type Estimate

type Estimate struct {
	LVal, Op, RVal   string
	Value            float64
	StdValue         float64
	Free             bool
	SE, Z, P         float64
	CILower, CIUpper float64
	Param            string
	// Label is the parameter's label in the description ("a*x"), ""
	// for an unlabelled one (whose Param is an auto name).
	Label string
}

Estimate is one row of the parameter table, laid out like semopy's Model.inspect(std_est=True): lval op rval, the estimate, the standardized estimate, and (free parameters only) SE, z and p.

An intercept / latent mean row has Op OpIntercept and an empty RVal. CILower / CIUpper are the Wald interval of a free parameter under lavaan conventions (Model.Lavaan), NaN otherwise.

func BootstrapGroupRows

func BootstrapGroupRows(fit *GroupFit) []Estimate

BootstrapGroupRows is a multi-group fit's table rows in table order: every group's estimates in fit order, then the := rows.

func BootstrapRows

func BootstrapRows(fit *Fit) []Estimate

BootstrapRows is a fit's parameter-table rows in table order: the estimates, then the := rows.

func SpecifiedDefined

func SpecifiedDefined(m *Model) []Estimate

SpecifiedDefined lists the model's defined-parameter rows with every figure NaN (SpecifiedRows' := half).

func SpecifiedRows

func SpecifiedRows(m *Model) []Estimate

SpecifiedRows lists the parameter-table rows of an unfitted model, in Fit.Estimates' order, with every figure NaN: the rows an undefined input still reports.

func (Estimate) Key

func (e Estimate) Key() string

Key is "lval op rval" ("lval ~1" for an intercept row).

type Estimator

type Estimator string

Estimator is a MAT_SEM estimator: maximum likelihood (the default) or one of lavaan's ordinal estimators.

const (
	// EstimatorML is maximum likelihood on the covariance (and means).
	EstimatorML Estimator = "ml"
	// EstimatorDWLS is lavaan's estimator = "DWLS": diagonally weighted
	// least squares on the two-step statistics, robust (sandwich)
	// standard errors, the standard test.
	EstimatorDWLS Estimator = "dwls"
	// EstimatorWLSMV is lavaan's estimator = "WLSMV": DWLS plus the
	// mean-and-variance adjusted (scaled-shifted) test.
	EstimatorWLSMV Estimator = "wlsmv"
)

func (Estimator) Ordinal

func (e Estimator) Ordinal() bool

Ordinal reports whether e is an ordinal (two-step) estimator.

type Fit

type Fit struct {
	Model      *Model
	N          float64
	Objective  float64 // the minimised Wishart ML discrepancy F
	Iterations int
	Converged  bool
	Status     string // the solver's exit message
	Options    Options
	Sample     *mat.SymDense // S over Model.Observed
	Implied    *mat.SymDense // Σ(θ̂)
	// SampleMean and ImpliedMean are ȳ and μ(θ̂) over Model.Observed
	// (Model.MeanStructure only; nil otherwise).
	SampleMean, ImpliedMean []float64
	Estimates               []Estimate
	// Defined are the := rows (defined.go), in description order, after
	// Estimates in every table; nil without a := line.
	Defined []Estimate
	Stats   Stats

	// Ordinal is an ordinal (DWLS / WLSMV) fit's stage-1 pieces and
	// estimator intermediates (FitOrdinal); nil on an ML fit.
	Ordinal *OrdinalFit
	// contains filtered or unexported fields
}

Fit is a fitted model.

func FitCov

func FitCov(m *Model, s *mat.SymDense, n float64, opt Options) (*Fit, error)

FitCov fits the model to a sample covariance matrix S (over m.Observed, divisor N — semopy's biased covariance) from n rows.

func FitCovNearest

func FitCovNearest(m *Model, adj, raw *mat.SymDense, n float64, opt Options) (*Fit, error)

FitCovNearest fits the model to adj, the CovNearest substitute for the data's covariance raw, as semopy fits it after load_cov's fallback: the objective, the Psi / Theta starts and every statistic read adj (semopy's mx_cov), while the Lambda starts are linregress slopes over the rows (mx_data), so they read raw.

func FitMoments

func FitMoments(m *Model, s, raw *mat.SymDense, mean []float64, n float64, opt Options) (*Fit, error)

FitMoments fits the model to the sample moments: S (adjusted, as FitCovNearest's adj, or the data's), the data's covariance raw and the sample mean (over m.Observed; required under a mean structure, ignored otherwise). A covariance-only model fits exactly as FitCovNearest.

func FitOrdinal

func FitOrdinal(m *Model, in TwoStepInput, est Estimator, opt Options) (*Fit, error)

FitOrdinal fits m (a model with ModelOptions.Ordered) by DWLS or WLSMV to in, the listwise-complete rows over m.Observed (an ordered column holds its category code 0..Levels-1, Kinds KindOrdered exactly on m's ordered variables; Weights frequency weights). A refused input is the two-step statistics' *OrdinalError.

func (*Fit) Params

func (f *Fit) Params() (Params, bool)

Params returns the fit's parameter matrices (a copy); false when the fit carries none (a fit not produced by this package's fitters). SampleMean is the fit's under a mean structure and nil otherwise — a covariance-only fit never reads the means, so a scorer's caller sets the fit rows' mean.

type Gamma

type Gamma struct {
	// Inner is Σ w·s·sᵀ (Size × Size).
	Inner [][]float64
	// A11 is the univariate information (Cor × Cor, block diagonal by
	// variable); A21 the correlation rows' cross information (pairs ×
	// Cor); A22 the correlations' own information (one per pair).
	A11 [][]float64
	A21 [][]float64
	A22 []float64
	// WLSW is lavaan's WLS.W: the asymptotic covariance of WLSObs
	// (Size × Size). NACOV is N·WLSW.
	WLSW [][]float64
	// N is the total weight Σw.
	N float64
}

Gamma is one group's asymptotic covariance of the two-step statistics and its pieces, every matrix in ScoreLayout coordinates (WLS.obs order: thresholds and numeric means, numeric variances, then the pairs).

func (*Gamma) NACOV

func (g *Gamma) NACOV() [][]float64

NACOV returns N·WLS.W, lavaan's NACOV (a fresh matrix).

type GroupFit

type GroupFit struct {
	// Labels are the groups' labels, in fit order.
	Labels []string
	// Groups are the per-group fits, index-aligned with Labels: each
	// one's Model, N (n_g), Objective (F_g), sample and implied moments
	// and Estimates (standard errors from the joint information). Each
	// group's Stats are zero; the joint figures are GroupFit.Stats.
	Groups []*Fit
	// N is the total row count Σ n_g.
	N float64
	// Objective is the minimised joint discrepancy Σ (n_g/N) F_g (twice
	// lavaan's fmin).
	Objective  float64
	Iterations int
	Converged  bool
	Status     string
	Options    Options
	// Stats are the joint statistics (lavaan's, over every group).
	Stats Stats
	// Chi2Group are the per-group chi-squares n_g F_g, summing to
	// Stats.Chi2.
	Chi2Group []float64
	// Defined are the := rows over the joint free vector and its
	// covariance (a label resolves to its group's parameter; a shared
	// one is one parameter), in description order; nil without a :=
	// line.
	Defined []Estimate
	// VCov is an ordinal fit's robust covariance of the joint free
	// vector (each group's OrdinalFit.Joint indexes it), and TraceUG /
	// TraceUG2 WLSMV's tr(UΓ) and tr((UΓ)²); nil and 0 on an ML fit.
	VCov              *mat.SymDense
	TraceUG, TraceUG2 float64
	// contains filtered or unexported fields
}

GroupFit is a fitted multi-group model.

func FitGroups

func FitGroups(model *Model, groups []GroupMoments, opt Options) (*GroupFit, error)

FitGroups fits model (NewGroupModel) jointly to every group's moments (at least two groups): the joint ML fit under lavaan's conventions — Fisher scoring to the optimum by default, standard errors from the joint expected information, lavaan's multiple-group statistics (ComputeStats is not needed).

func FitOrdinalGroups

func FitOrdinalGroups(model *Model, groups []OrdinalGroup, est Estimator, opt Options) (*GroupFit, error)

FitOrdinalGroups fits model (NewGroupModel with ModelOptions.Ordered) by DWLS or WLSMV jointly to every group's rows (at least two groups). A refused input is the group's two-step *OrdinalError (its Group the group's position in groups), a group_partial threshold row the data do not hold a *GroupSpecError.

type GroupMoments

type GroupMoments struct {
	Label     string
	S, Raw    *mat.SymDense
	Mean      []float64
	N         float64
	Level     int
	Reference bool
}

GroupMoments are one group's sample moments: S (adjusted, as FitMoments' s, or the data's), the data's covariance Raw, the sample mean and the row count, all over the model's Observed order. Level is the group's position in the per-group modifiers c(...) (its level index: a group without rows leaves its position unused); Reference marks the group whose latent means stay fixed at 0 and whose marker loadings stay fixed (lavaan's first group; none marked: the first).

type GroupSpecError

type GroupSpecError struct {
	Param, Value, Msg string
}

GroupSpecError is a refused multi-group equality spec: Param is the knob at fault (group_equal or group_partial), Value the entry.

func (*GroupSpecError) Error

func (e *GroupSpecError) Error() string

type Information

type Information string

Information selects how the expected information tr(Σ⁻¹∂Σ_kΣ⁻¹∂Σ_l) and the gradient are computed. Both give the same figures up to rounding.

const (
	// InformationDense forms every ∂Σ_k as a dense matrix, as semopy
	// does (the default).
	InformationDense Information = "dense"
	// InformationRank2 uses ∂Σ_k = Σ(a·bᵀ + b·aᵀ): every trace reduces
	// to dot products of Σ⁻¹-transformed vectors, O(k²·p) instead of
	// O(k·p³ + k²·p²).
	InformationRank2 Information = "rank2"
)

type Model

type Model struct {
	// Observed is the model's observed variables in semopy's order: the
	// sorted outputs (variables with no outgoing arrow), then the other
	// observed variables sorted. Sample and implied covariances use it.
	Observed []string
	// Inner is the non-output variables: sorted latents, then sorted
	// observed inner variables (Beta and Psi index it).
	Inner []string

	// MeanStructure is set when the fit models the means too
	// (ModelOptions.MeanStructure, or any `~ 1` statement): observed
	// intercepts (Nu, and Alpha for observed inner variables) and latent
	// means (Alpha) join the parameters, and the objective gains the
	// mean term.
	MeanStructure bool
	// contains filtered or unexported fields
}

Model is a parsed, specified SEM: the variable classification and the parameter table, before any data is seen.

func NewGroupModel

func NewGroupModel(desc string, opt ModelOptions) (*Model, error)

NewGroupModel specifies desc for a multi-group fit: the model every group's copy follows (the first group's per-group modifiers), with a mean structure and lavaan conventions whatever opt says, and opt's group_equal / group_partial validated (a *GroupSpecError).

func NewModel

func NewModel(desc string, baseline bool) (*Model, error)

NewModel specifies the model a description describes, with semopy's defaults (variances of every endogenous and latent variable free, observed exogenous (co)variances fixed to the sample, exogenous latents free to covary, the first indicator of each latent fixed to 1). baseline builds semopy's independence model instead.

func NewModelWithOptions

func NewModelWithOptions(desc string, opt ModelOptions) (*Model, error)

NewModelWithOptions specifies the model a description describes with the features opt selects (ModelOptions); NewModel(desc, false) is NewModelWithOptions(desc, ModelOptions{}).

func (*Model) Arity

func (m *Model) Arity() int

Arity is the per-group modifiers' length: the group count a description with c(...) lists fits (0: no per-group modifier).

func (*Model) CheckGroupCount

func (m *Model) CheckGroupCount(n int) error

CheckGroupCount refuses per-group modifiers whose length is not the group count n.

func (*Model) DefinedCount

func (m *Model) DefinedCount() int

DefinedCount is the model's := lines: the estimate rows a fit appends after the parameter table.

func (*Model) DefinedReads

func (m *Model) DefinedReads() map[string][]string

DefinedReads maps each := name to the labels it reads, directly or through an earlier := line, sorted.

func (*Model) IsOrdered

func (m *Model) IsOrdered(v string) bool

IsOrdered reports whether v is an ordered variable of the model.

func (*Model) Latents

func (m *Model) Latents() []string

Latents returns the model's latent variables in Inner order.

func (*Model) Lavaan

func (m *Model) Lavaan() bool

Lavaan reports whether the model follows lavaan's conventions rather than semopy's: true whenever a lavaan-only feature (a mean structure, a := defined parameter, ModelOptions.Lavaan — a bootstrap) is in play. Such a fit converges to the optimum (the default solver is Fisher scoring), leaves variances unbounded, and reports lavaan's chi-square, degrees of freedom, fit indices, log-likelihood and Wald intervals (ComputeStats); a covariance-only model keeps semopy's.

func (*Model) LevelLabels

func (m *Model) LevelLabels(level int) []string

LevelLabels lists the labels a multi-group model names at per-group position level — each c(...) list's level-th entry and every label outside one — sorted; nil when level is past the per-group lists or the description does not parse. The labels of a level that holds no rows are absent from the fit, so a := reading one is null.

func (*Model) Ordered

func (m *Model) Ordered() []string

Ordered returns the model's ordered variables in Observed order (nil when the fit is not ordinal).

type ModelOptions

type ModelOptions struct {
	// MeanStructure models the means: every observed intercept free
	// (an observed exogenous variable's mean fixed to its sample mean,
	// lavaan's fixed.x), every latent mean fixed to 0 unless a `f ~ 1`
	// statement frees it — lavaan's meanstructure = TRUE. A `~ 1`
	// statement in the description sets it too.
	MeanStructure bool
	// GroupEqual and GroupPartial are a multi-group model's (NewGroupModel)
	// lavaan group.equal values (GroupEqualValues) and group.partial
	// rows ("lhs op rhs", e.g. "x1~1", "f=~x2", "x1~~x2"): the
	// parameters of the named classes are one value across groups,
	// except the partial rows.
	GroupEqual, GroupPartial []string
	// Lavaan switches a covariance-only model to lavaan's conventions
	// (Model.Lavaan) with no lavaan-only syntax in the description: a
	// bootstrap (RunBootstrap) is lavaan's se = "bootstrap".
	Lavaan bool
	// Ordered names the ordered (ordinal) observed variables of a DWLS
	// / WLSMV fit (FitOrdinal), lavaan's ordered =, under the delta
	// parameterization: each is an indicator or an outcome (no outgoing
	// arrow) whose latent response has intercept 0 and implied variance
	// 1 — its residual variance is no parameter (the remainder) and
	// thresholds replace its mean. The model then follows lavaan's
	// conventions with a mean structure (lavaan's categorical default).
	// An observed exogenous variable is refused (lavaan conditions on it,
	// conditional.x), as are a `x ~ 1` or `x ~~ x` line on an ordered x.
	// Validated with an *OrdinalSpecError.
	Ordered []string
	// contains filtered or unexported fields
}

ModelOptions select the features beyond semopy's default covariance-structure model. The zero value is that model.

type Mult

type Mult struct {
	Set    bool
	Fixed  bool
	Value  float64
	Label  string
	Groups []Mult
	// contains filtered or unexported fields
}

Mult is the multiplier written before a right-hand variable: none (a free parameter), a fixed number ("0.5*x"), a parameter label ("a*x", equality across every place the label is used) or lavaan's NA ("NA*x": free, unlabelled — Set without Fixed or Label). A per-group modifier ("c(a1,a2)*x", "c(0.5,NA)*x") carries one of those per group in Groups, in level order; the model of group g reads Groups[g] (selectGroup).

type Nearest

type Nearest struct {
	// Cov is the adjusted covariance (S's diagonal, to rounding).
	Cov *mat.SymDense
	// MinEigenvalue is the smallest eigenvalue of S's correlation form,
	// before the clip.
	MinEigenvalue float64
	// Clipped reports whether any eigenvalue was below the threshold
	// (false: Cov is S rescaled through its correlation form unchanged).
	Clipped bool
}

Nearest is a cov_nearest result.

func CovNearest

func CovNearest(s *mat.SymDense, threshold float64) (*Nearest, error)

CovNearest is statsmodels' cov_nearest(s, method="clipped", threshold) (above). Every diagonal entry of s must be positive and finite: statsmodels' correlation form is undefined otherwise (its eigendecomposition of the NaN it produces fails).

type Options

type Options struct {
	// Solver is the optimiser (default SolverSLSQP).
	Solver Solver
	// Information is the derivative computation (default
	// InformationDense).
	Information Information
	// Ftol is SLSQP's ftol (default 1e-6, SciPy's and semopy's).
	Ftol float64
	// MaxIter caps the iterations (default 10000 for SLSQP — semopy's
	// setting — and 500 for Fisher scoring).
	MaxIter int
	// GradTol is Fisher scoring's stop: every free gradient entry below
	// it in absolute value (default 1e-10).
	GradTol float64
	// Level is the Wald interval's level (lavaan's level), in (0, 1);
	// 0 is 0.95. It sets ci_lower / ci_upper only (a lavaan-convention
	// fit's), never an estimate, SE or p.
	Level float64
}

Options configure the fit. The zero value is semopy's default setup.

func (Options) Validate

func (o Options) Validate() error

Validate reports an unknown solver or information mode.

type OrdinalError

type OrdinalError struct {
	Var, Group int
	Reason     string
	Freq       []float64
	Msg        string
}

OrdinalError is a refused two-step input: Var is the column at fault (-1 for the whole input), Group the group index (-1 ungrouped), Reason one of the Reason* codes, Freq an ordered column's weighted category frequencies when they are the reason.

func (*OrdinalError) Error

func (e *OrdinalError) Error() string

type OrdinalFit

type OrdinalFit struct {
	// Estimator is the fit's estimator.
	Estimator Estimator
	// Stats are the two-step statistics; Gamma their asymptotic
	// covariance.
	Stats *TwoStepStats
	Gamma *Gamma
	// Obs is WLS.obs; Est the model's WLS.est at the estimate; Weight
	// the diagonal weight 1/diag(NACOV).
	Obs, Est, Weight []float64
	// Delta is ∂WLS.est/∂θ at the estimate (rows Obs, columns the free
	// vector: the model's free parameters then the thresholds).
	Delta [][]float64
	// VCov is the free vector's robust covariance.
	VCov *mat.SymDense
	// TraceUG and TraceUG2 are tr(UΓ) and tr((UΓ)²) (WLSMV).
	TraceUG, TraceUG2 float64
	// FreeKeys are the free vector's row keys (Estimate.Key of each
	// parameter's first row; the thresholds "x | tk"; a grouped fit's
	// free scale factors "x ~*~ x").
	FreeKeys []string
	// Joint is a grouped fit's map from this group's free vector to the
	// joint one (GroupFit.VCov's coordinates; a shared parameter one
	// joint index); nil ungrouped, where Delta and VCov are the fit's
	// own.
	Joint []int
}

OrdinalFit is an ordinal fit's stage-1 pieces.

type OrdinalGroup

type OrdinalGroup struct {
	Label     string
	In        TwoStepInput
	Level     int
	Reference bool
}

OrdinalGroup is one group's rows for FitOrdinalGroups: the listwise-complete rows over the model's Observed order (every group's Kinds and Levels the same — the pooled coding), plus the group's place in the fit (GroupMoments' Label, Level and Reference).

type OrdinalKind

type OrdinalKind uint8

OrdinalKind is a two-step variable's measurement level.

const (
	// KindNumeric is a continuous variable (a mean and a variance).
	KindNumeric OrdinalKind = iota
	// KindOrdered is an ordinal variable: integer category codes
	// 0..Levels-1, read as a cut normal latent response.
	KindOrdered
)

type OrdinalSpecError

type OrdinalSpecError struct {
	Param, Var, Reason, Msg string
}

OrdinalSpecError is a refused ordinal specification (ModelOptions.Ordered): Param is the params key at fault ("ordered" or "model"), Var the variable, Reason a short code.

func (*OrdinalSpecError) Error

func (e *OrdinalSpecError) Error() string

type PairEstimate

type PairEstimate struct {
	I, J int
	Kind PairKind
	Rho  float64
	// Bound reports an estimate pinned on its box edge (±0.999 /
	// ±0.995): the likelihood still rose toward ±1.
	Bound bool
	// ZeroCells reports a polychoric table with an empty cell.
	ZeroCells bool
	// Closed reports a closed-form polychoric (a 2 × 2 table with
	// proportional margins, two empty cells, or both thresholds 0;
	// lavaan's lav_bvord_cor_twostep_fit shortcuts).
	Closed bool
}

PairEstimate is one bivariate two-step correlation. Pairs are in lavaan's layout: column-major below the diagonal, (1,0), (2,0), …, (p-1,0), (2,1), …, so I > J and the k-th pair is lavaan's k-th correlation (its WLS.obs order).

type PairKind

type PairKind uint8

PairKind is a two-step correlation's estimator.

const (
	// PairPearson is numeric × numeric: the ML (Pearson) correlation.
	PairPearson PairKind = iota
	// PairPolyserial is numeric × ordered: two-step ML polyserial.
	PairPolyserial
	// PairPolychoric is ordered × ordered: two-step ML polychoric.
	PairPolychoric
)

func (PairKind) String

func (k PairKind) String() string

type PairScore

type PairScore struct {
	Rho        float64
	ThI, ThJ   []float64
	VarI, VarJ float64
}

PairScore is one row's casewise scores of a bivariate log-likelihood (lavaan's lav_m84_pair_sc): Rho is ∂/∂ρ; ThI / ThJ are ∂/∂ the thresholds of column I / J (a numeric column: its mean, one value); VarI / VarJ are ∂/∂ a numeric column's variance (NaN for an ordered one).

type Params

type Params struct {
	Lambda, Beta, Psi, Theta [][]float64
	Nu, Alpha                []float64
	SampleMean               []float64
	// Thresholds are an ordinal fit's raw thresholds τ per Observed
	// variable (an ordered variable's Levels − 1, nil for a numeric
	// one); nil for an ML fit. Theta's ordered diagonal is then the
	// delta parameterization's residual 1/Δ² − common (EBM scores,
	// NewEBMScorer).
	Thresholds [][]float64
}

Params are one group's parameter matrices at the estimate — Lambda (Observed × Inner), Beta and Psi (Inner × Inner), Theta (Observed × Observed), Nu (Observed) and Alpha (Inner), the fixed values included — and the fit's sample mean over Observed (the center of a covariance-only fit's scores). Every slice is the fit's own copy.

type ScaledStats

type ScaledStats struct {
	Chi2, Chi2P                   float64
	ScalingFactor, ShiftParameter float64
	Chi2Baseline                  float64
	BaselineScalingFactor         float64
	CFI, TLI, RMSEA               float64
}

ScaledStats are WLSMV's scaled-shifted test and the indices it scales (lavaan's chisq.scaled, chisq.scaling.factor, shift.parameter, baseline.chisq.scaled, cfi.scaled, tli.scaled, rmsea.scaled).

type ScoreLayout

type ScoreLayout struct {
	// Th[v] is column v's first threshold (or mean) index; NTh[v] its
	// count (Levels-1, or 1 for a numeric column).
	Th, NTh []int
	// VarIdx[v] is a numeric column's variance index (-1 for ordered).
	VarIdx []int
	// Cor is the first correlation index; Size the total width.
	Cor, Size int
}

ScoreLayout is the column layout of Scores, lavaan's SC: the threshold block (each ordered column's Levels-1 thresholds, a numeric column's mean, in column order), then each numeric column's variance, then the correlations in Pairs order.

type ScoreMethod

type ScoreMethod string

ScoreMethod is a factor-score method.

const (
	ScoreRegression ScoreMethod = "regression"
	ScoreBartlett   ScoreMethod = "bartlett"
)

The lavPredict methods.

type Scorer

type Scorer struct {
	Weights []float64
	Center  []float64
	Base    float64
}

Scorer is one latent's linear scoring rule in one group: score = Base + Σ_i Weights[i]·(y_i − Center[i]), y over Observed.

func NewScorer

func NewScorer(m *Model, p Params, latent string, method ScoreMethod) (*Scorer, error)

NewScorer builds latent's scoring rule under method from one group's parameter matrices p of model m (the group's own model under a multi-group fit). ErrScoreSingular when the scores are undefined.

func (*Scorer) Score

func (s *Scorer) Score(y []float64) float64

Score is the row's score (y over Observed, every value present).

type Solver

type Solver string

Solver selects the optimiser.

const (
	// SolverSLSQP is SciPy's SLSQP as semopy calls it (the default): the
	// same iterates, the same early stop at ftol, the same result.
	SolverSLSQP Solver = "slsqp"
	// SolverFisher is damped Fisher scoring (Levenberg–Marquardt on the
	// expected information): converges to the optimum to GradTol.
	SolverFisher Solver = "fisher"
)

type Stats

type Stats struct {
	DoF          float64
	DoFBaseline  float64
	Chi2         float64
	Chi2P        float64
	Chi2Baseline float64
	CFI, GFI     float64
	AGFI, NFI    float64
	TLI, RMSEA   float64
	AIC, BIC     float64
	LogLik       float64
	NParams      int
	// Scaled is WLSMV's scaled-shifted test and scaled indices (nil on
	// every other fit).
	Scaled *ScaledStats
}

Stats are semopy.calc_stats' figures, with semopy's definitions — including its conventions: LogLik is the minimised discrepancy F (semopy's calc_likelihood returns obj_mlw), AIC = 2(k − F), BIC = ln(N)·k − 2F, and GFI equals NFI.

type TwoStepInput

type TwoStepInput struct {
	// Kinds is each column's measurement level.
	Kinds []OrdinalKind
	// Levels is each ordered column's category count (codes
	// 0..Levels-1; ignored for a numeric column). Every declared
	// category must hold weight (ReasonEmptyCategory).
	Levels []int
	// Rows are the complete observations, one value per column; an
	// ordered column holds its integer code.
	Rows [][]float64
	// Weights are per-row frequency weights; nil weighs every row 1.
	Weights []float64
}

TwoStepInput is one group's data for TwoStep.

type TwoStepStats

type TwoStepStats struct {
	// N is the total weight Σw; Rows the row count.
	N    float64
	Rows int
	// Kinds and Levels echo the input.
	Kinds  []OrdinalKind
	Levels []int
	// Thresholds are each ordered column's Levels-1 thresholds (nil for
	// a numeric column); Freq its weighted category frequencies.
	Thresholds [][]float64
	Freq       [][]float64
	// Mean and Var are a numeric column's mean and ML variance (Σw
	// divisor); an ordered column's latent response is standardised (0
	// and 1).
	Mean, Var []float64
	// Cor is the full symmetric correlation matrix (unit diagonal).
	Cor [][]float64
	// Pairs are the bivariate estimates in lavaan's order.
	Pairs []PairEstimate
}

TwoStepStats is one group's two-step sample statistics.

func TwoStep

func TwoStep(in TwoStepInput) (*TwoStepStats, error)

TwoStep computes one group's thresholds, means, variances and pairwise correlations.

func TwoStepGroups

func TwoStepGroups(in TwoStepInput, group []int, levels int) ([]*TwoStepStats, error)

TwoStepGroups computes the statistics per group: group[i] in 0..levels-1 is row i's group, and every group shares in's Kinds and Levels, so a category the pooled data holds but one group lacks is that group's ReasonEmptyCategory refusal (as lavaan refuses it).

func (*TwoStepStats) Gamma

func (s *TwoStepStats) Gamma(in TwoStepInput) (*Gamma, error)

Gamma computes the asymptotic covariance of s from in, the rows (and weights) s was computed from. A univariate block or a correlation information that does not invert, or a non-finite figure, is an OrdinalError with ReasonSingular.

func (*TwoStepStats) Layout

func (s *TwoStepStats) Layout() ScoreLayout

Layout returns the Scores layout of s.

func (*TwoStepStats) PairScores

func (s *TwoStepStats) PairScores(k int, row []float64) PairScore

PairScores returns row's casewise scores for Pairs[k].

func (*TwoStepStats) Scores

func (s *TwoStepStats) Scores(row, out []float64) error

Scores writes row's casewise score vector (ScoreLayout order; the univariate blocks are each column's own score, the correlation block each pair's ρ-score) into out, which must hold Layout().Size values.

func (*TwoStepStats) WLSObs

func (s *TwoStepStats) WLSObs() []float64

WLSObs returns the sample statistics in lavaan's WLS.obs layout (ScoreLayout order): each ordered column's thresholds and a numeric column's NEGATED mean, the numeric variances, then every pair's covariance — the correlation times the standard deviations, so an ordered × ordered pair's is its polychoric correlation as is.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL