Skill Tracer
Skills › Scientific Agent Skills › statistical-analysis › assumptions_and_diagnostics.md

assumptions_and_diagnostics.md

377 lines · skills/statistical-analysis/references/assumptions_and_diagnostics.md at 5f2bc03

Open on GitHub
1# Statistical Assumptions and Diagnostic Procedures
2
3This document provides comprehensive guidance on checking and validating statistical assumptions for various analyses.
4

Statistical Assumptions and Diagnostic Procedures

This document provides comprehensive guidance on checking and validating statistical assumptions for various analyses.

Raw lines 1 to 4
5## General Principles
6
71. **Always check assumptions before interpreting test results**
82. **Use multiple diagnostic methods** (visual + formal tests)
93. **Consider robustness**: Some tests are robust to violations under certain conditions
104. **Document all assumption checks** in analysis reports
115. **Report violations and remedial actions taken**

General Principles

  1. Always check assumptions before interpreting test results
  2. Use multiple diagnostic methods (visual + formal tests)
  3. Consider robustness: Some tests are robust to violations under certain conditions
  4. Document all assumption checks in analysis reports
  5. Report violations and remedial actions taken
Raw lines 5 to 12
13## Common Assumptions Across Tests

Common Assumptions Across Tests

Raw lines 13 to 14
15### 1. Independence of Observations
17**What it means**: Each observation is independent; measurements on one subject do not influence measurements on another.
19**How to check**:
20- Review study design and data collection procedures
21- For time series: Check autocorrelation (ACF/PACF plots, Durbin-Watson test)
22- For clustered data: Consider intraclass correlation (ICC)
24**What to do if violated**:
25- Use mixed-effects models for clustered/hierarchical data
26- Use time series methods for temporally dependent data
27- Use generalized estimating equations (GEE) for correlated data
29**Critical severity**: HIGH - violations can severely inflate Type I error
31---

1. Independence of Observations

What it means: Each observation is independent; measurements on one subject do not influence measurements on another.

How to check:

  • Review study design and data collection procedures
  • For time series: Check autocorrelation (ACF/PACF plots, Durbin-Watson test)
  • For clustered data: Consider intraclass correlation (ICC)

What to do if violated:

  • Use mixed-effects models for clustered/hierarchical data
  • Use time series methods for temporally dependent data
  • Use generalized estimating equations (GEE) for correlated data

Critical severity: HIGH - violations can severely inflate Type I error


Raw lines 15 to 32
33### 2. Normality
35**What it means**: Data or residuals follow a normal (Gaussian) distribution.
37**When required**:
38- Small-sample normal-theory t/ANOVA inference: the relevant errors (paired differences for paired tests), not arbitrary pooled data
39- Linear regression: normal errors support exact finite-sample t/F inference; coefficient estimation itself does not require normal outcomes or predictors
40- Some correlation tests (Pearson)
42**How to check**:
44**Visual methods** (primary):
45- Q-Q (quantile-quantile) plot: Points should fall on diagonal line
46- Histogram with normal curve overlay
47- Kernel density plot
49**Formal tests** (secondary):
50- Shapiro-Wilk test (good default; scipy handles n up to ~5000 and warns above that)
51- Lilliefors test (`statsmodels.stats.diagnostic.lilliefors`) — use this instead of a plain Kolmogorov-Smirnov test, which is invalid when the mean/SD are estimated from the data
52- Anderson-Darling test
54**Python implementation**:
55```python
56from scipy import stats
57import matplotlib.pyplot as plt
59# Shapiro-Wilk test
60statistic, p_value = stats.shapiro(data)
62# Q-Q plot
63stats.probplot(data, dist="norm", plot=plt)
64```
66**Interpretation guidance**:
67- Assess plots, tail behavior, sample balance, dependence and the estimand at every sample size. Formal tests have low power in small samples and detect tiny departures in large samples; non-rejection does not validate a model.
68- Look for severe skewness, outliers, or bimodality
70**What to do if violated**:
71- **Departures**: Evaluate robustness for the target effect and design; there is no universal n=30 threshold. Prespecify robust inference or simulation-based sensitivity. Rank methods change the target and retain assumptions; they are not automatic replacements.
72- **Severe violations**:
73 - Transform data (log, square root, Box-Cox)
74 - Use non-parametric methods
75 - Use robust regression methods
76 - Consider bootstrapping
78**Critical severity**: MEDIUM - parametric tests are often robust to mild violations with adequate sample size
80---

2. Normality

What it means: Data or residuals follow a normal (Gaussian) distribution.

When required:

  • Small-sample normal-theory t/ANOVA inference: the relevant errors (paired differences for paired tests), not arbitrary pooled data
  • Linear regression: normal errors support exact finite-sample t/F inference; coefficient estimation itself does not require normal outcomes or predictors
  • Some correlation tests (Pearson)

How to check:

Visual methods (primary):

  • Q-Q (quantile-quantile) plot: Points should fall on diagonal line
  • Histogram with normal curve overlay
  • Kernel density plot

Formal tests (secondary):

  • Shapiro-Wilk test (good default; scipy handles n up to ~5000 and warns above that)
  • Lilliefors test (statsmodels.stats.diagnostic.lilliefors) — use this instead of a plain Kolmogorov-Smirnov test, which is invalid when the mean/SD are estimated from the data
  • Anderson-Darling test

Python implementation:

from scipy import stats
import matplotlib.pyplot as plt

# Shapiro-Wilk test
statistic, p_value = stats.shapiro(data)

# Q-Q plot
stats.probplot(data, dist="norm", plot=plt)

Interpretation guidance:

  • Assess plots, tail behavior, sample balance, dependence and the estimand at every sample size. Formal tests have low power in small samples and detect tiny departures in large samples; non-rejection does not validate a model.
  • Look for severe skewness, outliers, or bimodality

What to do if violated:

  • Departures: Evaluate robustness for the target effect and design; there is no universal n=30 threshold. Prespecify robust inference or simulation-based sensitivity. Rank methods change the target and retain assumptions; they are not automatic replacements.
  • Severe violations:
  • Transform data (log, square root, Box-Cox)
  • Use non-parametric methods
  • Use robust regression methods
  • Consider bootstrapping

Critical severity: MEDIUM - parametric tests are often robust to mild violations with adequate sample size


Raw lines 33 to 81
82### 3. Homogeneity of Variance (Homoscedasticity)
84**What it means**: Variances are equal across groups or across the range of predictors.
86**When required**:
87- Pooled Student's t-test and classical equal-variance ANOVA (not Welch tests)
88- Usual homoscedastic OLS standard errors; HC3 addresses independent heteroscedastic errors, not clusters
90**How to check**:
92**Visual methods** (primary):
93- Box plots by group (for t-test/ANOVA)
94- Residuals vs. fitted values plot (for regression) - should show random scatter
95- Scale-location plot (square root of standardized residuals vs. fitted)
97**Formal tests** (secondary):
98- Levene's test (robust to non-normality)
99- Bartlett's test (sensitive to non-normality, not recommended)
100- Brown-Forsythe test (median-based version of Levene's)
101- Breusch-Pagan test (for regression)
103**Python implementation**:
104```python
105from scipy import stats
106import pingouin as pg
108# Median-centered Levene is the Brown-Forsythe variance test
109statistic, p_value = stats.levene(group1, group2, group3, center='median')
111# For regression
112# Breusch-Pagan test
113# Note: exog must include the constant column (e.g. exog = sm.add_constant(X),
114# or pass the fitted model's model.exog)
115from statsmodels.stats.diagnostic import het_breuschpagan
116_, p_value, _, _ = het_breuschpagan(residuals, exog)
117```
119**Interpretation guidance**:
120- No variance-ratio cutoff certifies validity. Balanced designs can help robustness but do not remove tail, dependence or variance concerns.
121- Do not choose pooled versus Welch inference based only on a preliminary variance p-value.
122- For regression: Look for funnel patterns in residual plots
124**What to do if violated**:
125- **t-test**: Use Welch's t-test (does not assume equal variances)
126- **ANOVA**: Use Welch's ANOVA or Brown-Forsythe ANOVA
127- **Regression**:
128 - Transform dependent variable (log, square root)
129 - Use weighted least squares (WLS)
130 - Use robust standard errors (HC3)
131 - Use generalized linear models (GLM) with appropriate variance function
133**Critical severity**: MEDIUM - tests can be robust with equal sample sizes
135---

3. Homogeneity of Variance (Homoscedasticity)

What it means: Variances are equal across groups or across the range of predictors.

When required:

  • Pooled Student's t-test and classical equal-variance ANOVA (not Welch tests)
  • Usual homoscedastic OLS standard errors; HC3 addresses independent heteroscedastic errors, not clusters

How to check:

Visual methods (primary):

  • Box plots by group (for t-test/ANOVA)
  • Residuals vs. fitted values plot (for regression) - should show random scatter
  • Scale-location plot (square root of standardized residuals vs. fitted)

Formal tests (secondary):

  • Levene's test (robust to non-normality)
  • Bartlett's test (sensitive to non-normality, not recommended)
  • Brown-Forsythe test (median-based version of Levene's)
  • Breusch-Pagan test (for regression)

Python implementation:

from scipy import stats
import pingouin as pg

# Median-centered Levene is the Brown-Forsythe variance test
statistic, p_value = stats.levene(group1, group2, group3, center='median')

# For regression
# Breusch-Pagan test
# Note: exog must include the constant column (e.g. exog = sm.add_constant(X),
# or pass the fitted model's model.exog)
from statsmodels.stats.diagnostic import het_breuschpagan
_, p_value, _, _ = het_breuschpagan(residuals, exog)

Interpretation guidance:

  • No variance-ratio cutoff certifies validity. Balanced designs can help robustness but do not remove tail, dependence or variance concerns.
  • Do not choose pooled versus Welch inference based only on a preliminary variance p-value.
  • For regression: Look for funnel patterns in residual plots

What to do if violated:

  • t-test: Use Welch's t-test (does not assume equal variances)
  • ANOVA: Use Welch's ANOVA or Brown-Forsythe ANOVA
  • Regression:
  • Transform dependent variable (log, square root)
  • Use weighted least squares (WLS)
  • Use robust standard errors (HC3)
  • Use generalized linear models (GLM) with appropriate variance function

Critical severity: MEDIUM - tests can be robust with equal sample sizes


Raw lines 82 to 136
137## Test-Specific Assumptions

Test-Specific Assumptions

Raw lines 137 to 138
139### T-Tests
141**Assumptions**:
1421. Independence of observations
1432. Normality (each group for independent t-test; differences for paired t-test)
1443. Homogeneity only for pooled Student's independent t-test; Welch permits unequal variances
146**Diagnostic workflow**:
147```python
148import scipy.stats as stats
149import pingouin as pg
151# Check normality for each group
152stats.shapiro(group1)
153stats.shapiro(group2)
155# Check homogeneity of variance
156stats.levene(group1, group2)
158# Prespecify inference from the design/estimand rather than the screening p-values:
159# Option 1: Welch's t-test (unequal variances)
160pg.ttest(group1, group2, correction=True) # correction=True applies Welch's
161# (correction='auto' applies Welch only when sample sizes are unequal;
162# correction=False forces Student's t-test)
164# Option 2: A separately justified rank/distribution question
165pg.mwu(group1, group2) # Mann-Whitney U
166```
168---

T-Tests

Assumptions:

  1. Independence of observations
  2. Normality (each group for independent t-test; differences for paired t-test)
  3. Homogeneity only for pooled Student's independent t-test; Welch permits unequal variances

Diagnostic workflow:

import scipy.stats as stats
import pingouin as pg

# Check normality for each group
stats.shapiro(group1)
stats.shapiro(group2)

# Check homogeneity of variance
stats.levene(group1, group2)

# Prespecify inference from the design/estimand rather than the screening p-values:
# Option 1: Welch's t-test (unequal variances)
pg.ttest(group1, group2, correction=True)  # correction=True applies Welch's
# (correction='auto' applies Welch only when sample sizes are unequal;
# correction=False forces Student's t-test)

# Option 2: A separately justified rank/distribution question
pg.mwu(group1, group2)  # Mann-Whitney U

Raw lines 139 to 169
170### ANOVA
172**Assumptions**:
1731. Independence of observations within and between groups
1742. Normality in each group
1753. Homogeneity of variance across groups
177**Additional considerations**:
178- For repeated measures ANOVA: Sphericity assumption (Mauchly's test)
180**Diagnostic workflow**:
181```python
182import pingouin as pg
183from scipy import stats
185# Check normality per group
186for group in df['group'].unique():
187 data = df[df['group'] == group]['value']
188 w, p = stats.shapiro(data)
189 print(f"{group}: W = {w:.3f}, p = {p:.4f}")
191# Check homogeneity of variance
192print(pg.homoscedasticity(df, dv='value', group='group'))
194# For repeated measures: Check sphericity
195# Pingouin 0.7 supports one/two-way sphericity diagnostics; earlier interaction
196# corrections had bugs. Specify subject IDs and complete within-subject cells.
197```
199**What to do if sphericity violated** (repeated measures):
200- Prespecify a correction such as Greenhouse-Geisser; Pingouin rm_anova reports GG.
201- Do not infer Huynh-Feldt is automatically available from an epsilon threshold.
202- Use multivariate approach (MANOVA)
204---

ANOVA

Assumptions:

  1. Independence of observations within and between groups
  2. Normality in each group
  3. Homogeneity of variance across groups

Additional considerations:

  • For repeated measures ANOVA: Sphericity assumption (Mauchly's test)

Diagnostic workflow:

import pingouin as pg
from scipy import stats

# Check normality per group
for group in df['group'].unique():
    data = df[df['group'] == group]['value']
    w, p = stats.shapiro(data)
    print(f"{group}: W = {w:.3f}, p = {p:.4f}")

# Check homogeneity of variance
print(pg.homoscedasticity(df, dv='value', group='group'))

# For repeated measures: Check sphericity
# Pingouin 0.7 supports one/two-way sphericity diagnostics; earlier interaction
# corrections had bugs. Specify subject IDs and complete within-subject cells.

What to do if sphericity violated (repeated measures):

  • Prespecify a correction such as Greenhouse-Geisser; Pingouin rm_anova reports GG.
  • Do not infer Huynh-Feldt is automatically available from an epsilon threshold.
  • Use multivariate approach (MANOVA)

Raw lines 170 to 205
206### Linear Regression
208**Assumptions**:
2091. **Mean specification**: Conditional mean is linear in fitted coefficients (can include justified nonlinear predictor terms)
2102. **Independence**: Residuals are independent
2113. **Homoscedasticity**: Constant variance of residuals
2124. **Normality**: Normal errors for exact small-sample conventional inference; fitted residuals are correlated projections, so residual Shapiro is only a screen
2135. **Identifiability**: Full-rank design; high collinearity affects precision but is not by itself bias
2146. **Exogeneity**: The conditional error mean is zero; residual plots do not establish causal identification
216**Diagnostic workflow**:
218**1. Linearity**:
219```python
220import matplotlib.pyplot as plt
221import seaborn as sns
223# Scatter plots of Y vs each X
224# Residuals vs. fitted values (should be randomly scattered)
225plt.scatter(fitted_values, residuals)
226plt.axhline(y=0, color='r', linestyle='--')
227```
229**2. Independence**:
230```python
231from statsmodels.stats.stattools import durbin_watson
233# Durbin-Watson test (for time series)
234dw_statistic = durbin_watson(residuals)
235# Meaningful row order is required; no universal 1.5-2.5 acceptance interval.
236# This statistic cannot establish independence, particularly for clustered data.
237```
239**3. Homoscedasticity**:
240```python
241# Breusch-Pagan test
242# Note: exog must include the constant column (e.g. sm.add_constant(X))
243from statsmodels.stats.diagnostic import het_breuschpagan
244_, p_value, _, _ = het_breuschpagan(residuals, exog)
246# Visual: Scale-location plot
247plt.scatter(fitted_values, np.sqrt(np.abs(std_residuals)))
248```
250**4. Normality of residuals**:
251```python
252# Q-Q plot of residuals
253stats.probplot(residuals, dist="norm", plot=plt)
255# Shapiro-Wilk test
256stats.shapiro(residuals)
257```
259**5. Multicollinearity**:
260```python
261from statsmodels.stats.outliers_influence import variance_inflation_factor
263# Calculate VIF for each predictor
264vif_data = pd.DataFrame()
265vif_data["feature"] = X.columns
266vif_data["VIF"] = [variance_inflation_factor(X.values, i) for i in range(len(X.columns))]
268# VIF > 10 indicates severe multicollinearity
269# VIF > 5 indicates moderate multicollinearity
270```
272**What to do if violated**:
273- **Non-linearity**: Add polynomial terms, use GAM, or transform variables
274- **Heteroscedasticity**: Transform Y, use WLS, use robust SE
275- **Non-normal residuals**: Transform Y, use robust methods, check for outliers
276- **Multicollinearity**: Examine precision and identification; dropping confounders can bias estimates. Regularization changes inference and must match the purpose.
278---

Linear Regression

Assumptions:

  1. Mean specification: Conditional mean is linear in fitted coefficients (can include justified nonlinear predictor terms)
  2. Independence: Residuals are independent
  3. Homoscedasticity: Constant variance of residuals
  4. Normality: Normal errors for exact small-sample conventional inference; fitted residuals are correlated projections, so residual Shapiro is only a screen
  5. Identifiability: Full-rank design; high collinearity affects precision but is not by itself bias
  6. Exogeneity: The conditional error mean is zero; residual plots do not establish causal identification

Diagnostic workflow:

1. Linearity:

import matplotlib.pyplot as plt
import seaborn as sns

# Scatter plots of Y vs each X
# Residuals vs. fitted values (should be randomly scattered)
plt.scatter(fitted_values, residuals)
plt.axhline(y=0, color='r', linestyle='--')

2. Independence:

from statsmodels.stats.stattools import durbin_watson

# Durbin-Watson test (for time series)
dw_statistic = durbin_watson(residuals)
# Meaningful row order is required; no universal 1.5-2.5 acceptance interval.
# This statistic cannot establish independence, particularly for clustered data.

3. Homoscedasticity:

# Breusch-Pagan test
# Note: exog must include the constant column (e.g. sm.add_constant(X))
from statsmodels.stats.diagnostic import het_breuschpagan
_, p_value, _, _ = het_breuschpagan(residuals, exog)

# Visual: Scale-location plot
plt.scatter(fitted_values, np.sqrt(np.abs(std_residuals)))

4. Normality of residuals:

# Q-Q plot of residuals
stats.probplot(residuals, dist="norm", plot=plt)

# Shapiro-Wilk test
stats.shapiro(residuals)

5. Multicollinearity:

from statsmodels.stats.outliers_influence import variance_inflation_factor

# Calculate VIF for each predictor
vif_data = pd.DataFrame()
vif_data["feature"] = X.columns
vif_data["VIF"] = [variance_inflation_factor(X.values, i) for i in range(len(X.columns))]

# VIF > 10 indicates severe multicollinearity
# VIF > 5 indicates moderate multicollinearity

What to do if violated:

  • Non-linearity: Add polynomial terms, use GAM, or transform variables
  • Heteroscedasticity: Transform Y, use WLS, use robust SE
  • Non-normal residuals: Transform Y, use robust methods, check for outliers
  • Multicollinearity: Examine precision and identification; dropping confounders can bias estimates. Regularization changes inference and must match the purpose.

Raw lines 206 to 279
280### Logistic Regression
282**Assumptions**:
2831. **Independence**: Observations are independent
2842. **Linearity**: Linear relationship between log-odds and continuous predictors
2853. **No perfect multicollinearity**: Predictors not perfectly correlated
2864. **Information and identification**: Adequate events/non-events for parameters, effect sizes and precision; check separation and convergence. No fixed events-per-variable ratio guarantees valid inference.
288**Diagnostic workflow**:
290**1. Linearity of logit**:
291```python
292# Box-Tidwell test: Add interaction with log of continuous predictor
293# If interaction is significant, linearity violated
294```
296**2. Multicollinearity**:
297```python
298# Use VIF as in linear regression
299```
301**3. Influential observations**:
302```python
303# Cook's distance, DFBetas, leverage (statsmodels >= 0.10)
304# Do NOT use OLSInfluence on Logit/GLM results; use get_influence(),
305# which returns MLEInfluence (Logit) or GLMInfluence (GLM)
306influence = model.get_influence()
307cooks_d, cooks_p = influence.cooks_distance # tuple: (distances, approximate p-values)
308# Outside Gaussian linear models these F-based p-values are approximate.
309```
311**4. Model fit / calibration**:
312```python
313# Calibration curve: compare predicted probabilities to observed event rates
314# (e.g. sklearn.calibration.calibration_curve), plus the Brier score
315# Pseudo R-squared
316# Classification metrics (accuracy, AUC-ROC)
317# Note: the Hosmer-Lemeshow test is not implemented in scipy/statsmodels
318# and is sensitive to the choice of bins; prefer calibration curves
319```
321---

Logistic Regression

Assumptions:

  1. Independence: Observations are independent
  2. Linearity: Linear relationship between log-odds and continuous predictors
  3. No perfect multicollinearity: Predictors not perfectly correlated
  4. Information and identification: Adequate events/non-events for parameters, effect sizes and precision; check separation and convergence. No fixed events-per-variable ratio guarantees valid inference.

Diagnostic workflow:

1. Linearity of logit:

# Box-Tidwell test: Add interaction with log of continuous predictor
# If interaction is significant, linearity violated

2. Multicollinearity:

# Use VIF as in linear regression

3. Influential observations:

# Cook's distance, DFBetas, leverage (statsmodels >= 0.10)
# Do NOT use OLSInfluence on Logit/GLM results; use get_influence(),
# which returns MLEInfluence (Logit) or GLMInfluence (GLM)
influence = model.get_influence()
cooks_d, cooks_p = influence.cooks_distance  # tuple: (distances, approximate p-values)
# Outside Gaussian linear models these F-based p-values are approximate.

4. Model fit / calibration:

# Calibration curve: compare predicted probabilities to observed event rates
# (e.g. sklearn.calibration.calibration_curve), plus the Brier score
# Pseudo R-squared
# Classification metrics (accuracy, AUC-ROC)
# Note: the Hosmer-Lemeshow test is not implemented in scipy/statsmodels
# and is sensitive to the choice of bins; prefer calibration curves

Raw lines 280 to 322
323## Outlier Detection
325**Methods**:
3261. **Visual**: Box plots, scatter plots
3272. **Statistical**:
328 - Z-scores: |z| > 3 suggests outlier
329 - IQR method: Values < Q1 - 1.5×IQR or > Q3 + 1.5×IQR
330 - Modified Z-score using median absolute deviation (robust to outliers)
332**For regression**:
333- **Leverage**: High leverage points (hat values)
334- **Influence**: Cook's distance > 4/n suggests influential point
335- **Outliers**: Studentized residuals > ±3
337**What to do**:
3381. Investigate data entry errors
3392. Consider if outliers are valid observations
3403. Report sensitivity analysis (results with and without outliers)
3414. Use robust methods if outliers are legitimate
343---

Outlier Detection

Methods:

  1. Visual: Box plots, scatter plots
  2. Statistical:
  3. Z-scores: |z| > 3 suggests outlier
  4. IQR method: Values < Q1 - 1.5×IQR or > Q3 + 1.5×IQR
  5. Modified Z-score using median absolute deviation (robust to outliers)

For regression:

  • Leverage: High leverage points (hat values)
  • Influence: Cook's distance > 4/n suggests influential point
  • Outliers: Studentized residuals > ±3

What to do:

  1. Investigate data entry errors
  2. Consider if outliers are valid observations
  3. Report sensitivity analysis (results with and without outliers)
  4. Use robust methods if outliers are legitimate

Raw lines 323 to 344
345## Sample Size Considerations

Sample Size Considerations

Raw lines 345 to 346
347### Design-specific planning
349Plan using the target effect or desired interval width, variance, prevalence, number of fitted parameters, clustering and attrition. Generic n=30/n=50 or events-per-variable thresholds do not establish power, robustness or model reliability. Simulate the actual planned estimator/design when closed-form assumptions do not apply.

Design-specific planning

Plan using the target effect or desired interval width, variance, prevalence, number of fitted parameters, clustering and attrition. Generic n=30/n=50 or events-per-variable thresholds do not establish power, robustness or model reliability. Simulate the actual planned estimator/design when closed-form assumptions do not apply.

Raw lines 347 to 350
351### Small Sample Considerations
353For small samples:
354- Assumptions become more critical
355- Use exact tests when available (Fisher's exact, exact logistic regression)
356- Consider non-parametric alternatives
357- Use permutation tests or bootstrap methods
358- Be conservative with interpretation
360---

Small Sample Considerations

For small samples:

  • Assumptions become more critical
  • Use exact tests when available (Fisher's exact, exact logistic regression)
  • Consider non-parametric alternatives
  • Use permutation tests or bootstrap methods
  • Be conservative with interpretation

Raw lines 351 to 361
362## Reporting Assumption Checks
364When reporting analyses, include:
3661. **Statement of assumptions checked**: List all assumptions tested
3672. **Methods used**: Describe visual and formal tests employed
3683. **Results of diagnostic tests**: Report test statistics and p-values
3694. **Assessment**: State evidence of departures and limits of the screens; never equate non-rejection with verified assumptions
3705. **Actions taken**: If violated, describe remedial actions (transformations, alternative tests, robust methods)
372**Example reporting statement**:
373> "Normality was assessed using Shapiro-Wilk tests and Q-Q plots. Data for Group A (W = 0.97, p = .18) and Group B (W = 0.96, p = .12) showed no significant departure from normality. Homogeneity of variance was assessed using Levene's test, which was non-significant (F(1, 58) = 1.23, p = .27), providing no detected departure from equal variances at this sample size. Non-rejection does not verify equality; the prespecified Welch test and design review were retained."

Reporting Assumption Checks

When reporting analyses, include:

  1. Statement of assumptions checked: List all assumptions tested
  2. Methods used: Describe visual and formal tests employed
  3. Results of diagnostic tests: Report test statistics and p-values
  4. Assessment: State evidence of departures and limits of the screens; never equate non-rejection with verified assumptions
  5. Actions taken: If violated, describe remedial actions (transformations, alternative tests, robust methods)

Example reporting statement:

"Normality was assessed using Shapiro-Wilk tests and Q-Q plots. Data for Group A (W = 0.97, p = .18) and Group B (W = 0.96, p = .12) showed no significant departure from normality. Homogeneity of variance was assessed using Levene's test, which was non-significant (F(1, 58) = 1.23, p = .27), providing no detected departure from equal variances at this sample size. Non-rejection does not verify equality; the prespecified Welch test and design review were retained."
Raw lines 362 to 374
375## Current API sources
377Reviewed 2026-10-01: [SciPy Shapiro](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.shapiro.html) requires at least three observations and warns that n>5000 p-values may be inaccurate; [Levene](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.levene.html) defaults to median centering. [statsmodels Breusch-Pagan](https://www.statsmodels.org/stable/generated/statsmodels.stats.diagnostic.het_breuschpagan.html) defaults to the Koenker variant (`robust=True`), needs an intercept, and also returns the finite-sample F variant; report which one is used. [Durbin-Watson](https://www.statsmodels.org/stable/generated/statsmodels.stats.stattools.durbin_watson.html) is a statistic of adjacent residuals, not an independence certificate.

Current API sources

Reviewed 2026-10-01: SciPy Shapiro requires at least three observations and warns that n>5000 p-values may be inaccurate; Levene defaults to median centering. statsmodels Breusch-Pagan defaults to the Koenker variant (robust=True), needs an intercept, and also returns the finite-sample F variant; report which one is used. Durbin-Watson is a statistic of adjacent residuals, not an independence certificate.

Raw lines 375 to 377