Transformations Module ====================== Unit-specific panel data transformations for difference-in-differences. This module implements unit-specific outcome transformations that remove pre-treatment heterogeneity from panel data. Transformation parameters are estimated using only pre-treatment observations, then applied out-of-sample to all periods including post-treatment. The transformations convert panel difference-in-differences estimation into cross-sectional treatment effects problems, enabling the application of various estimators (regression adjustment, inverse probability weighting, doubly robust, matching) to the transformed outcomes. .. automodule:: lwdid.transformations :no-members: Available Transformations ------------------------- demean ~~~~~~ Removes unit-specific pre-treatment mean: .. math:: \dot{Y}_{it} = Y_{it} - \bar{Y}_{i,pre} where :math:`\bar{Y}_{i,pre} = T_0^{-1} \sum_{s= 1. No seasonal support. Assumes parallel levels (common trends). - **detrend**: Pre-periods required >= 2. No seasonal support. Allows heterogeneous linear trends. - **demeanq**: Pre-periods required >= Q+1. Seasonal support (Q=4/12/52). Assumes parallel levels (common trends). - **detrendq**: Pre-periods required >= Q+2. Seasonal support (Q=4/12/52). Allows heterogeneous linear trends. Staggered Adoption Transformations ---------------------------------- For staggered adoption designs, transformations are applied separately for each treatment cohort :math:`g`, using cohort-specific pre-treatment periods. This approach follows Lee and Wooldridge (2025). Cohort-Specific Demeaning ~~~~~~~~~~~~~~~~~~~~~~~~~~ For cohort :math:`g` (units first treated in period :math:`g`) and calendar time :math:`r \geq g`, the transformed outcome is computed as: .. math:: \dot{Y}_{irg} = Y_{ir} - \bar{Y}_{i,pre(g)} where the cohort-specific pre-treatment mean is: .. math:: \bar{Y}_{i,pre(g)} = \frac{1}{g-1} \sum_{s=1}^{g-1} Y_{is} The key difference from common timing demeaning is that the pre-treatment average uses only periods :math:`\{1, 2, \ldots, g-1\}` specific to each cohort, rather than a fixed set of pre-treatment periods for all units. **Requirements**: For each cohort :math:`g`, at least :math:`g - 1 \geq 1` pre-treatment periods must exist. Early cohorts (e.g., :math:`g = 2`) may have limited pre-treatment data. Cohort-Specific Detrending ~~~~~~~~~~~~~~~~~~~~~~~~~~~ For cohort :math:`g` and calendar time :math:`r \geq g`, the detrended outcome is: .. math:: \ddot{Y}_{irg} = Y_{ir} - \hat{A}_{ig} - \hat{B}_{ig} \cdot r where :math:`(\hat{A}_{ig}, \hat{B}_{ig})` are estimated from the unit-specific regression using only pre-treatment periods for cohort :math:`g`: .. math:: Y_{it} = A_i + B_i \cdot t + \varepsilon_{it}, \quad t \in \{1, 2, \ldots, g-1\} This removes both unit-specific levels and unit-specific linear trends, allowing for heterogeneous trend paths across units while preserving the treatment variation for estimation. **Requirements**: For each cohort :math:`g`, at least :math:`g - 1 \geq 2` pre-treatment periods must exist to estimate both intercept and slope. Staggered Transformation Usage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The staggered transformations are applied automatically when the ``gvar`` parameter is specified in ``lwdid()``: .. code-block:: python from lwdid import lwdid # Staggered demeaning results = lwdid( data, y='outcome', ivar='unit', tvar='year', gvar='first_treat_year', # Cohort indicator rolling='demean' ) # Staggered detrending results = lwdid( data, y='outcome', ivar='unit', tvar='year', gvar='first_treat_year', rolling='detrend' ) Staggered Transformation Selection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In staggered adoption designs, only the ``demean`` and ``detrend`` transformations are supported through the main ``lwdid()`` interface. Seasonal transformations (``demeanq``, ``detrendq``) are restricted to common timing mode; passing ``rolling='demeanq'`` or ``rolling='detrendq'`` with ``gvar`` raises a ``ValueError``. - **demean**: Staggered support via ``lwdid()`` = Yes. Pre-periods required: :math:`g - 1 \geq 1` per cohort. - **detrend**: Staggered support via ``lwdid()`` = Yes. Pre-periods required: :math:`g - 1 \geq 2` per cohort. - **demeanq**: Staggered support via ``lwdid()`` = No (common timing only). - **detrendq**: Staggered support via ``lwdid()`` = No (common timing only). .. note:: The staggered module contains low-level implementations of ``transform_staggered_demeanq`` and ``transform_staggered_detrendq`` for advanced users, but these are not exposed through the main ``lwdid()`` function. See Also -------- :func:`lwdid.lwdid` : Main estimation function. :doc:`../methodological_notes` : Theoretical foundations of transformations. :doc:`../user_guide` : Practical guidance on transformation selection.