Skip to content

Commit a2c235e

Browse files
igerberclaude
andcommitted
Add ICC feasibility guard for zero non-PSU variance
Raise ValueError when icc is set but unit_fe_sd=0, noise_sd=0, and add_covariates=False, since the target ICC is unattainable with zero non-PSU variance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 11d8501 commit a2c235e

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

diff_diff/prep_dgp.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,8 +1405,14 @@ def generate_survey_did_data(
14051405
# Include covariate variance: Var(0.5*x1) + Var(0.3*x2)
14061406
# where x1 ~ N(0,1), x2 ~ Bernoulli(0.5)
14071407
cov_var = (0.25 + 0.09 * 0.25) if add_covariates else 0.0
1408+
non_psu_var = unit_fe_sd**2 + noise_sd**2 + cov_var
1409+
if non_psu_var < 1e-12:
1410+
raise ValueError(
1411+
"icc requires non-zero non-PSU variance "
1412+
"(unit_fe_sd, noise_sd, or add_covariates must contribute variance)"
1413+
)
14081414
psu_re_sd = np.sqrt(
1409-
icc * (unit_fe_sd**2 + noise_sd**2 + cov_var)
1415+
icc * non_psu_var
14101416
/ ((1 - icc) * (1 + psu_period_factor**2))
14111417
)
14121418

tests/test_prep.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,15 @@ def test_icc_parameter(self):
15311531
realized_icc = (msb - msw) / (msb + (n_bar - 1) * msw)
15321532
assert abs(realized_icc - target_icc) / target_icc < 0.50
15331533

1534+
def test_icc_zero_variance_rejected(self):
1535+
"""icc with zero non-PSU variance should raise ValueError."""
1536+
from diff_diff.prep_dgp import generate_survey_did_data
1537+
1538+
with pytest.raises(ValueError, match="non-zero non-PSU variance"):
1539+
generate_survey_did_data(
1540+
icc=0.3, unit_fe_sd=0, noise_sd=0, add_covariates=False, seed=42
1541+
)
1542+
15341543
def test_icc_and_psu_re_sd_conflict(self):
15351544
"""Cannot specify both icc and a non-default psu_re_sd."""
15361545
from diff_diff.prep_dgp import generate_survey_did_data

0 commit comments

Comments
 (0)