Impute a next-menses onset from a confirmed ovulation (Internal)
Source:R/impute_next_menses.R
impute_next_menses_onsets.RdImplements the GENERAL next-menses imputation rule: for each
biomarker-confirmed ovulation (ovtoday == 1) that has NO observed menses
onset recorded anywhere after it for that person, synthesize a menses onset
at ovulation + luteal_days (the population-average luteal length, so
ovulation + 14 = the "LH+15"/last-follicular-day rule). This lets a confirmed
ovulation whose next menses was never recorded at all still contribute a
scalable cycle, rather than being dropped for lack of a closing anchor.
Usage
impute_next_menses_onsets(
data,
id,
date,
menses,
ovtoday,
luteal_days = 14,
max_window = 20
)Arguments
- data
A data frame in long format (one row per id-date).
- id, date, menses, ovtoday
Unquoted column names, as in
pacts_scaling().- luteal_days
Days after ovulation to place the imputed onset. Default 14.
- max_window
Not currently used to gate the impute decision – kept for argument-signature stability; a non-default value has no effect on the result. Through 0.1.6, imputation fired whenever no OBSERVED menses onset fell within
max_windowdays after a confirmed ovulation (default 20). That was a real bug, not a documented tradeoff: a genuine luteal phase just outside the window (confirmed on this package's owncycledataexample, id 8: a real 22-day luteal phase) got a fabricated onset synthesized at day 14 anyway, which OVERWROTE that participant's actually observedmenses == 0day to1– corrupting real data, not just adding an imputed row. As of 0.1.7 a real closing menses at ANY distance always prevents imputation; only a confirmed ovulation with NO recorded closing menses anywhere in that person's remaining data is treated as open. SeeNEWS.mdfor the full history.
Value
data with imputed menses onsets added (existing rows updated, or new
rows appended for onset dates outside the observed range) and a
menses_impute indicator column.
Details
A real, observed closing menses – at ANY distance from the ovulation, not
just a nearby one – always wins and is never overridden or duplicated by an
imputed onset (see the max_window entry below for why this search is
deliberately unbounded as of 0.1.7).
Study-specific gating (e.g. blocking imputation across treatment phases or documented off-study breaks, trust-ordered de-duplication of anchors) is deliberately NOT done here; it is the caller's responsibility to apply on top. This function does the general rule only.
Operates on the user's own id / date / menses / ovtoday columns and is
run before cycle-length calculation, so downstream scaling sees the augmented
anchors. Imputed onsets are marked in a new menses_impute column (1 =
imputed onset, 0 = everything else).