---
title: "Using heteroTests"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Using heteroTests}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#")
```

The **heteroTests** package provides several classical tests for detecting heteroscedasticity in linear models.

```{r example}
library(heteroTests)

# Fit a simple linear model on real data
model <- lm(stations ~ mag + depth, data = quakes)
# A second dataset demonstrates collinearity and mild nonlinearity
data(diagnostic_data)
diag_model <- lm(y ~ x1 + x2, data = diagnostic_data)

# Run White's test and get an htest object
performWhiteTest(model, quakes)
performWhiteTest(diag_model, diagnostic_data)
```

## Other available tests

Many additional diagnostics follow the same interface and also return an
`htest` object.

```{r more-tests}
# Breusch-Pagan and its robust Koenker version. The data argument must be
# the data the model was fitted on.
performBPTest(model, quakes)
performKoenkerTest(model, quakes)

# Group-based tests need a grouping factor in that same data
quakes_grouped <- quakes
quakes_grouped$depth_band <- cut(quakes_grouped$depth, 3,
                                 labels = c("shallow", "mid", "deep"))
performLeveneTest(model, quakes_grouped, "depth_band")

# ARCH effects in time series
performArchLMTest(model, lags = 2)
```

Several diagnostics can also be run together.

```{r run-many}
# Alternatively run multiple tests at once
runHeteroTests(model, quakes)
# Choose a subset of diagnostics
runHeteroTests(model, quakes, tests = c("white", "koenker", "ncv"))
runDiagnostics(model, quakes)
```

Remediation helpers operate on the fitted model directly.

```{r remediation}
fitWLS(model)
fitRobust(model)
autoTransform(model)
```

See the package README for a complete list of implemented tests.

## Earthquake station-count example

R's built-in `quakes` dataset records 1,000 seismic events near Fiji. We can run the diagnostics and attempt a remedial fit on this real-world data.

```{r quakes-example}
quakes_model <- lm(stations ~ mag + depth, data = quakes)
runDiagnostics(quakes_model, quakes)
fitWLS(quakes_model)
```

## Theophylline dosing example

The `Theoph` dataset from base R contains blood concentration measures after
a single dose. Diagnostics reveal heteroscedasticity and let us visualise
the residual spread.

```{r theoph-example}
data(Theoph, package = "datasets")
dose_model <- lm(conc ~ Time, data = Theoph)
performWhiteTest(dose_model, Theoph)
plot(HeteroDiagnostic(dose_model, Theoph))
```

## Step-by-step workflow

This short example shows how to detect heteroscedasticity, choose a remedy and re-test the model.

```{r step-by-step}
hd <- HeteroDiagnostic(stations ~ mag + depth, quakes)
test(hd)

wls_model <- fitWLS(hd$model)

# Re-test after remedy
test(HeteroDiagnostic(wls_model, quakes))
```

The drop in test statistics or diagnostic plots indicates whether the remedy helped.

## Statistical Accuracy and Validation

The `heteroTests` package implementations have been validated against:

- **Original published papers** with known test cases
- **Established R packages** (lmtest, car, stats)  
- **Commercial software** results (Stata, EViews)
- **Simulation studies** with known statistical properties

### Cross-Package Validation

```{r validation-example}
# Compare our Breusch-Pagan test with lmtest
library(lmtest)
data(mtcars)
model <- lm(mpg ~ wt + hp, data = mtcars)

# Our implementation
our_result <- performBreuschPaganTest(model, mtcars)

# Reference implementation
ref_result <- bptest(model)

# Results should match
print(paste("Our statistic:", round(our_result$statistic, 6)))
print(paste("Reference statistic:", round(ref_result$statistic, 6)))
```

## Performance and Memory Considerations

### Large Datasets

The `heteroTests` package is designed to handle datasets of various sizes, but some considerations apply:

- **Memory warnings**: Functions will warn when processing large datasets (>50MB)
- **Computational time**: Some tests (White, Breusch-Pagan) can be slow on very large datasets
- **Memory usage**: Peak memory usage is typically 2-3x the dataset size

### Recommendations for Large Datasets

```{r performance-tips, eval=FALSE}
# Illustrative only: `your_data` stands for your own data frame, so this
# chunk is not evaluated when the vignette is built.

# 1. Subset for initial exploration
large_subset <- your_data[sample(nrow(your_data), 1000), ]
quick_result <- performWhiteTest(model, large_subset)

# 2. Use simpler tests first
fast_result <- performGQTest(model, your_data, order_by = "x1")

# 3. Monitor memory usage
gc()  # Garbage collection before analysis
result <- performWhiteTest(model, your_data)
gc()  # Clean up after
```

### Memory Management Tips

- Use `gc()` to free memory between analyses
- Consider processing data in chunks for very large datasets
- Close unused objects with `rm()` to free memory
