Problem statement
Currently, the shift_doses() function offers two options for the shift_mode parameter:
"full": Shifts the full proportion calculated from the vaccination schedule table and birth seasonality (or uniform seasonality if not provided)
"partial": Shifts only the integer part of the proportion
However, in real-world settings, children do not receive vaccines at exact, deterministic ages as specified on vaccination schedules. There is natural fluctuation due to factors such as:
- Clinic appointment availability
- Caregiver schedules and delays
- Early or late vaccination practices
- Regional variations in schedule adherence
Neither "full" nor "partial" captures this real-world variability, potentially leading to overly precise estimates that don't reflect actual vaccination patterns.
Proposed solution
Add a "random" option to shift_mode that introduces stochastic variation to the age of dose receipt while maintaining the overall schedule-based proportions as the expected value.
Behavior specification:
- Like
"full", starts with the proportion calculated from the vaccination schedule and birth seasonality
- Applies random noise (e.g., drawn from a truncated normal or uniform distribution) to shift the age of administration
- Allows users to control the magnitude of fluctuation via a new parameter (e.g.,
fluctuation_sd or age_jitter)
- Maintains the same overall expected coverage proportions as
"full" but with individual-level variability
- Optionally allows different distributions (normal, uniform, or triangular) to model different delay patterns
Key parameters for the updated function:
shift_mode = "random"
fluctuation_sd (default = 1 month): standard deviation of age fluctuation
fluctuation_dist (default = "normal"): distribution of random shifts
Example usage
library(pviem)
# Using random shifting with default fluctuation parameters
shift_doses(
ri_data = vaccination_data,
shift_mode = "random",
# ... other parameters
)
# Customizing fluctuation magnitude and distribution
shift_doses(
ri_data = vaccination_data,
shift_mode = "random",
fluctuation_sd = 1.5, # 1.5 months standard deviation
fluctuation_dist = "uniform", # uniform distribution of delays
# ... other parameters
)
# For reproducible results
set.seed(123)
shift_doses(
ri_data = vaccination_data,
shift_mode = "random",
fluctuation_sd = 1,
# ... other parameters
)
Alternatives considered
- Extending
"partial" with jitter: Could add jitter to integer shifts only, but this wouldn't capture the full proportion shifting behavior
- User-provided delay distribution: Allow users to supply a custom probability distribution for age shifts - more flexible but more complex for typical users
- Bootstrap approach: Resample from observed age-at-vaccination data if available - requires additional data that users may not have
- Deterministic age windows: Use age windows (e.g., "month 2-4") instead of point estimates - simpler but doesn't capture continuous variation
- The proposed
"random" option strikes a balance between simplicity for users and realistic modeling of vaccination age variability.
Additional context
Why this matters:
Vaccination coverage models that assume exact schedule adherence can:
- Underestimate true coverage when there is natural variation
- Create artificial precision that doesn't reflect real-world uncertainty
- Miss important patterns in delayed or early vaccination
Implementation considerations:
- Random shifts should respect boundaries (e.g., no negative ages, no shifting beyond reasonable windows)
- The function should support reproducible results via
set.seed()
- Consider performance implications of stochastic operations in loops
- Document that results will vary between runs unless seed is set
Potential future extensions:
- Allow correlation between doses (children who are late for one dose tend to be late for subsequent doses)
- Support time-varying fluctuation parameters (e.g., more variability for later doses)
Checklist
Problem statement
Currently, the
shift_doses()function offers two options for theshift_modeparameter:"full": Shifts the full proportion calculated from the vaccination schedule table and birth seasonality (or uniform seasonality if not provided)"partial": Shifts only the integer part of the proportionHowever, in real-world settings, children do not receive vaccines at exact, deterministic ages as specified on vaccination schedules. There is natural fluctuation due to factors such as:
Neither
"full"nor"partial"captures this real-world variability, potentially leading to overly precise estimates that don't reflect actual vaccination patterns.Proposed solution
Add a
"random"option toshift_modethat introduces stochastic variation to the age of dose receipt while maintaining the overall schedule-based proportions as the expected value.Behavior specification:
"full", starts with the proportion calculated from the vaccination schedule and birth seasonalityfluctuation_sdorage_jitter)"full"but with individual-level variabilityKey parameters for the updated function:
shift_mode = "random"fluctuation_sd(default = 1 month): standard deviation of age fluctuationfluctuation_dist(default = "normal"): distribution of random shiftsExample usage
Alternatives considered
"partial"with jitter: Could add jitter to integer shifts only, but this wouldn't capture the full proportion shifting behavior"random"option strikes a balance between simplicity for users and realistic modeling of vaccination age variability.Additional context
Why this matters:
Vaccination coverage models that assume exact schedule adherence can:
Implementation considerations:
set.seed()Potential future extensions:
Checklist