Skip to content

Factors & model

Factors

factors

Factor abstractions with natural <-> coded conversion.

CategoricalFactor dataclass

CategoricalFactor(name, levels)

Bases: Factor

Categorical factor with arbitrary level labels.

Encoding maps each level to an integer index 0 .. k-1 for dummy coding in the model matrix; decoding maps indices back to level labels.

Parameters:

Name Type Description Default
name str

Factor name.

required
levels sequence

Category labels (at least two).

required

Raises:

Type Description
ValueError

When fewer than two levels are given.

Examples:

>>> import doekit as ed
>>> f = ed.CategoricalFactor("cat", ["A", "B"])
>>> f.encode("B")
1

ContinuousFactor dataclass

ContinuousFactor(name, low, high)

Bases: Factor

Continuous factor with standard two-level coding to [-1, +1].

Natural values on [low, high] map linearly to coded [-1, +1] for response-surface and optimal-design routines.

Formulas

coded = 2 * (x - low) / (high - low) - 1

x = low + (coded + 1) / 2 * (high - low)

Parameters:

Name Type Description Default
name str

Factor name.

required
low float

Lower bound in natural units.

required
high float

Upper bound in natural units.

required

Raises:

Type Description
ValueError

When low == high.

Examples:

>>> import doekit as ed
>>> f = ed.ContinuousFactor("temp", 20.0, 80.0)
>>> float(f.encode(50.0))
0.0

DiscreteFactor dataclass

DiscreteFactor(name, levels)

Bases: Factor

Numeric factor with a finite ordered level set.

Encoding uses the range from the smallest to largest level mapped to [-1, +1]; decoding snaps to the nearest discrete level.

Formulas

Same linear coding as :class:ContinuousFactor on [levels[0], levels[-1]]; decode selects argmin |x - level|.

Parameters:

Name Type Description Default
name str

Factor name.

required
levels sequence of float

Allowed numeric levels (at least two, sorted on init).

required

Raises:

Type Description
ValueError

When fewer than two levels are given.

Examples:

>>> import doekit as ed
>>> f = ed.DiscreteFactor("dose", [10, 20, 30])
>>> f.decode(-1.0)
10.0

Factor

Bases: ABC

Common interface for experimental factors.

Concrete types (:class:~doekit.domain.factors.ContinuousFactor, :class:~doekit.domain.factors.DiscreteFactor, etc.) implement :meth:encode / :meth:decode between natural and coded units and :meth:to_dict for serialization. Do not instantiate this ABC directly.

Attributes:

Name Type Description
name str

Factor name (matches a run-matrix column).

is_categorical property

is_categorical

Whether the factor is categorical (dummy-coded in the model matrix).

decode abstractmethod

decode(coded)

Map coded values back to natural units.

encode abstractmethod

encode(values)

Map natural-unit values to coded units for model construction.

to_dict abstractmethod

to_dict()

Serialize the factor to a plain dict.

MixtureFactor dataclass

MixtureFactor(name, lower=0.0, upper=1.0)

Bases: Factor

Mixture component for Scheffé / simplex designs.

Values are proportions on [lower, upper] subject to sum x_i = 1 across components. Encoding is the identity (proportions are not mapped to ±1); the experimental region is a simplex, not a hypercube.

Formulas

Constraint: sum_i x_i = 1 with lower_i <= x_i <= upper_i.

Parameters:

Name Type Description Default
name str

Component name.

required
lower float

Lower bound on the proportion.

0.0
upper float

Upper bound on the proportion.

1.0

Raises:

Type Description
ValueError

When bounds violate 0 <= lower < upper <= 1.

Examples:

>>> import doekit as ed
>>> f = ed.MixtureFactor("A")
>>> float(f.encode(0.5))
0.5

encode

encode(values)

Return proportions unchanged (identity coding for Scheffé models).

as_factors

as_factors(spec)

Normalize a flexible factor specification to list[Factor].

Accepts an integer (that many default continuous factors on [-1, 1]), a dict {name: (low, high)} or {name: [levels]}, or a sequence of :class:Factor instances.

Parameters:

Name Type Description Default
spec int or dict or sequence of Factor

Factor specification in any supported form.

required

Returns:

Type Description
list of Factor

Normalized factor list.

Examples:

>>> import doekit as ed
>>> ed.as_factors(2)[0].name
'factor1'
>>> ed.as_factors({"A": (0, 1)})[0].name
'A'

decode_frame

decode_frame(matrix, factors)

Return a copy of matrix with coded columns decoded to natural units.

encode_frame

encode_frame(matrix, factors)

Return a copy of matrix with continuous/discrete columns coded to ±1.

Categorical factors are left raw (the model dummy-codes them). Mixture proportions stay as-is (identity coding for Scheffé). Columns with no associated factor are assumed already coded.

factor_from_dict

factor_from_dict(d)

Rebuild a :class:Factor from its :meth:to_dict output.

Parameters:

Name Type Description Default
d dict

Serialized factor with a type key and type-specific fields.

required

Returns:

Type Description
Factor

Restored factor instance.

Raises:

Type Description
UnknownFactorTypeError

When type is not registered.

Examples:

>>> import doekit as ed
>>> f = ed.ContinuousFactor("x", 0, 10)
>>> ed.factor_from_dict(f.to_dict()).name
'x'

register_factor_type

register_factor_type(type_name, factory)

Register a factor type key for :func:factor_from_dict (open/closed).

Parameters:

Name Type Description Default
type_name str

Serialization type key (e.g. "continuous").

required
factory callable

factory(dict) -> Factor rebuilds a factor from a dict payload.

required

Model

model

Model specification DSL and model-matrix construction.

Interaction dataclass

Interaction(names)

Interaction term: element-wise product of factor columns.

Parameters:

Name Type Description Default
names tuple of str

Factor names whose columns are multiplied (order preserved in label).

required

Examples:

>>> import doekit as ed
>>> ed.Interaction(("A", "B")).label()
'A:B'

Intercept dataclass

Intercept()

Constant (intercept) column of ones in the model matrix.

Appears as (Intercept) in column labels. Omitted in Scheffé mixture models where the constraint sum x_i = 1 replaces the intercept.

Examples:

>>> import doekit as ed
>>> ed.Intercept().label()
'(Intercept)'

Main dataclass

Main(name)

Main-effect term for a single factor.

The model column is the factor column from the run matrix (after any coding applied upstream).

Parameters:

Name Type Description Default
name str

Factor name (must match a run-matrix column).

required

Examples:

>>> import doekit as ed
>>> ed.Main("temperature").label()
'temperature'

Model

Model(terms, response=None)

An ordered set of terms that builds a model matrix X.

Terms (:class:Intercept, :class:Main, :class:Interaction, :class:Power) define columns of X from a run matrix. Construct via :meth:parse, :meth:from_terms, or presets (:meth:full_quadratic, :meth:main_effects, Scheffé helpers).

Parameters:

Name Type Description Default
terms sequence of Term

Ordered list of model terms (intercept first when present).

required
response str

Response variable name (metadata only; not used in matrix construction).

None

Examples:

>>> import doekit as ed
>>> m = ed.Model.parse("y ~ x1 + x2 + x1:x2")
>>> "x1:x2" in [t.label() for t in m.terms]
True

factor_names property

factor_names

Unique factor names referenced by all terms (order of first appearance).

column_names

column_names(df)

Return model-matrix column labels for a run frame.

Parameters:

Name Type Description Default
df DataFrame

Run matrix whose columns supply factor values.

required

Returns:

Type Description
list of str

One label per model column (matches :meth:matrix column order).

from_dict classmethod

from_dict(d)

Rebuild a :class:Model from :meth:to_dict output.

Parameters:

Name Type Description Default
d dict

Serialized model.

required

Returns:

Type Description
Model

Restored model instance.

from_terms classmethod

from_terms(terms, response=None, intercept=True)

Build a model from an explicit term list.

Parameters:

Name Type Description Default
terms sequence of Term

Model terms (intercept may be included explicitly).

required
response str

Response variable name.

None
intercept bool

Insert :class:Intercept when absent.

True

Returns:

Type Description
Model

Model with the given terms.

full_quadratic classmethod

full_quadratic(factor_names, intercept=True)

Full quadratic response-surface model (main + interactions + squares).

Parameters:

Name Type Description Default
factor_names sequence of str

Factor names for mains, pairwise interactions, and ^2 terms.

required
intercept bool

Include an intercept.

True

Returns:

Type Description
Model

Model with all main effects, two-factor interactions, and pure quadratics.

Examples:

>>> import doekit as ed
>>> m = ed.Model.full_quadratic(["A", "B"])
>>> len(m.terms) >= 5  # intercept + 2 mains + interaction + 2 squares
True

main_effects classmethod

main_effects(factor_names, intercept=True)

Main-effects-only model.

Parameters:

Name Type Description Default
factor_names sequence of str

Factor names for main-effect columns.

required
intercept bool

Include an intercept.

True

Returns:

Type Description
Model

Model with one :class:Main term per factor.

Examples:

>>> import doekit as ed
>>> ed.Model.main_effects(["x1", "x2"], intercept=False).terms[0]
Main(name='x1')

matrix

matrix(df)

Build the model matrix X from a run DataFrame.

Parameters:

Name Type Description Default
df DataFrame

Run matrix with columns for each factor referenced by terms.

required

Returns:

Type Description
(ndarray, shape(n_runs, n_params))

Model matrix X.

parse classmethod

parse(formula)

Parse a formula-like string into a :class:Model.

Supports + for main effects, : for interactions, ^ for powers, and -1 / 0 to omit the intercept.

Parameters:

Name Type Description Default
formula str

Formula such as "y ~ x1 + x2 + x1:x2 + x3^2" or "x1 + x2".

required

Returns:

Type Description
Model

Parsed model with an intercept unless -1 or 0 appears.

Examples:

>>> import doekit as ed
>>> ed.Model.parse("y ~ x1 + x2").factor_names
['x1', 'x2']

scheffe_linear classmethod

scheffe_linear(factor_names)

Scheffé linear mixture model (no intercept).

Formulas

y = sum_i beta_i x_i with sum_i x_i = 1.

Parameters:

Name Type Description Default
factor_names sequence of str

Mixture component names.

required

Returns:

Type Description
Model

Linear Scheffé model without intercept.

scheffe_quadratic classmethod

scheffe_quadratic(factor_names)

Scheffé quadratic mixture model (no intercept).

Formulas

Linear Scheffé terms plus cross products x_i x_j for i < j.

Parameters:

Name Type Description Default
factor_names sequence of str

Mixture component names.

required

Returns:

Type Description
Model

Quadratic Scheffé model without intercept.

to_dict

to_dict()

Serialize the model to a plain dict.

Returns:

Type Description
dict

Keys response and terms (each term's :meth:~Term.to_dict).

Power dataclass

Power(name, degree)

Polynomial term: a factor column raised to an integer degree.

Parameters:

Name Type Description Default
name str

Factor name.

required
degree int

Exponent (typically 2 for pure quadratic terms).

required

Examples:

>>> import doekit as ed
>>> ed.Power("x", 2).label()
'x^2'

term_from_dict

term_from_dict(d)

Rebuild a term from its :meth:to_dict output.