cleverly.datasets.make_longitudinal#

cleverly.datasets.make_longitudinal(n: int = 2000, *, seed: int | Generator | None = None, censoring: bool = True, cluster_size: int | None = None, backend: Literal['pandas', 'polars'] | str | None = None) → tuple[Any, dict[str, float]][source]#

Two time points, a binary outcome and (optionally) monotone censoring.

Returns (frame, truth). The frame is wide – a row per unit, a column per node – with columns W1, W2, A1, C1, L2, A2, C2, Y in time order, and the nodes after a unit’s censoring time set to nan, which is the form LongitudinalData requires.

truth holds ey_regimen[...] for the four static regimens, for the dynamic regimen RULE_LABEL, and the contrasts of always and of that rule against never – under the labels a fit reports them by, so a test can look up the truth with the name it read off the result. A rule is in there because a coverage study keys into truth by reported name and so cannot supply its own.

cluster_size adds an id column and, with it, a per-cluster component of L2 – so the influence curves are correlated within a cluster and ignoring id= understates the standard error. There is an id column over independent rows otherwise, which makes a cluster-robust variance equal the plain one and tests nothing. truth holds on a clustered draw, and for a reason rather than by assertion: the sharing preserves L2’s standard normal noise marginal exactly, which is the law longitudinal_truth() integrates over. See _shared_within_clusters(), which also says why the hidden-variable construction this replaced did not.

Parameters:
nint

Number of units.

seedint, Generator, or None

Seed or NumPy random generator.

censoringbool

Whether to generate monotone censoring. False leaves every unit observed.

cluster_sizeint or None

Rows per cluster. None leaves the rows independent.

backend{“pandas”, “polars”, “pyarrow”} or None, default=None

Dataframe backend. None uses pandas when installed, then the first available backend.

Returns:
dataframe

Wide-format observations, one row per unit and one column per node.

truthdict of str to float

Regimen means and contrasts, under the labels a fit reports them by.

See also

cleverly.LongitudinalTreatment

The design declaration for the nodes above.

cleverly.longitudinal.LongitudinalResult

What a fit on this frame returns.

cleverly.datasets.make_longitudinal_survival

The same shape with an event outcome.

Examples

>>> from cleverly.datasets import make_longitudinal
>>> frame, truth = make_longitudinal(n=200, seed=0)
>>> list(frame.columns)
['W1', 'W2', 'A1', 'C1', 'L2', 'A2', 'C2', 'Y']
>>> round(truth["ate_regimen[always vs never]"], 3)
0.362