cleverly.longitudinal.LongitudinalData.from_long_panel#
- classmethod LongitudinalData.from_long_panel(data: Any, *, unit: str, time: str, treatment: str | Sequence[str], baseline: Sequence[str], time_varying: Sequence[str] = (), censoring: str | None = None, outcome: str | None = None, event: str | Mapping[str, str] | None = None, times: Sequence[Any] | None = None, cluster: str | None = None, weights: str | None = None, weights_type: str = 'probability', weights_estimated: bool = False, family: str = 'auto', continuous_treatment: bool = False, treatment_probabilities: Mapping[Any, str] | None = None, censoring_probabilities: str | None = None) LongitudinalData[source]#
Build from a long panel: one row per unit and decision time.
Each row holds the covariates measured before that row’s decision, the decision, and whether the unit is still observed after it. The rows of one unit form one trajectory, and the trajectory is one observation: repeated rows add no independent observations. Units that depend on each other, such as the customers of one account, declare
cluster=.The container is the one
from_frame()builds from the equivalent wide frame. Nodetis thet-th decision time. A columncmeasured at nodetis named"c@t"inhistory_frame()andpolicy_frame(), andeach_node()writes a rule that reads it. Rows may arrive in any order. The container’s rows follow the sorted unit identifiers.- Parameters:
- data
DataFrame A pandas or polars frame with one row per unit and decision time.
- unit
str The unit identifier column. Identifiers must sort, so use one type.
- time
str The decision-time column. Times must sort.
- treatment
stror sequenceofstr The decision at each row. A list of columns is one vector node per time.
- baselinesequence
ofstr Unit-level covariates measured before the first decision. Each is recorded on the unit’s first row and holds one value per unit.
- time_varyingsequence
ofstr Covariates measured at each row before that row’s decision. A measurement taken after the decision belongs to the next row. A column with no value at the first nodes, such as a lag, starts at its first recorded node.
- censoring
strorNone 1where the unit is still observed after the row’s decision, and0on the last row of a unit that left.Nonemeans every unit has a row at every decision time, or leaves through the event.- outcome
strorNone An end-of-study outcome: one value per unit, on any of its rows.
- event
strormappingofstrtostrorNone A survival outcome: an event indicator on each row,
1on the row of the event. A mapping of cause label to column declares competing risks. Declare exactly one ofoutcomeandevent.- timessequence or
None Every decision time, in time order; the order given is the node order.
Noneuses the times the panel holds, sorted, and needs numbers, dates or durations.- cluster
strorNone The cluster identifier, constant within a unit.
- weights
strorNone A unit-level probability weight.
- weights_type{“probability”}
How to read
weights, as forfrom_frame().- weights_estimatedbool
Whether the weights came out of a fitted model.
- family{“auto”, “gaussian”, “binomial”}
The outcome family.
- continuous_treatmentbool
Whether the treatment column holds a continuous dose at every node.
- treatment_probabilities
mappingofleveltostr,orNone The known treatment mechanism: each level mapped to the column that holds
P(A_t = level | past)on each row.- censoring_probabilities
strorNone The column that holds
P(C_t = 1 | past)on each row.
- data
- Returns:
LongitudinalDataThe container, with
panelandunit_idsset.
- Raises:
DataErrorFor a missing unit or time, a duplicated
(unit, time)row, a unit that starts late or skips a decision time, rows after a unit left, a unit whose rows stop without leaving, a unit-level column that varies within a unit or is first recorded after the first row, a column in two roles, a covariate that copies the outcome or the event, an event recorded on a censored row, a time-varying column that stops being recorded, and a treatment that never changes within a unit. Every check offrom_frame()applies as well.
See also
to_long_panelThe inverse.
cleverly.LongPanelThe same input as a study design.
cleverly.longitudinal.each_nodeOne rule for every node.
Examples
A panel of 20 customers over two weeks. Customer 3 leaves after week 1, so its censoring is 0 on its one row and its outcome is missing.
>>> import numpy as np >>> import pandas as pd >>> from cleverly.longitudinal import LongitudinalData >>> rng = np.random.default_rng(0) >>> panel = pd.DataFrame( ... { ... "customer": np.repeat(np.arange(20), 2), ... "week": np.tile([1, 2], 20), ... "age": np.repeat(rng.normal(size=20), 2), ... "eng": rng.normal(size=40), ... "offer": rng.choice(["none", "offer"], size=40), ... "active": 1.0, ... "bought": np.repeat(rng.integers(0, 2, size=20), 2).astype(float), ... } ... ) >>> panel = panel.drop(index=7) >>> panel.loc[6, ["active", "bought"]] = [0.0, np.nan] >>> data = LongitudinalData.from_long_panel( ... panel, ... unit="customer", ... time="week", ... treatment="offer", ... baseline=["age"], ... time_varying=["eng"], ... censoring="active", ... outcome="bought", ... ) >>> data.n, data.n_times (20, 2) >>> data.history_names(2) ('age', 'eng@1', 'eng@2')