|
| 1 | +# AGENTS.md — pdp |
| 2 | + |
| 3 | +R package for **partial dependence plots (PDPs)** and **individual conditional |
| 4 | +expectation (ICE) curves** from fitted ML models. Exports: `partial()` (the |
| 5 | +workhorse), `plot()` methods (tinyplot/base graphics, default engine), |
| 6 | +`plotPartial()` (lattice), `exemplar()`, and the deprecated `topPredictors()`. |
| 7 | + |
| 8 | +## Branches & releases |
| 9 | + |
| 10 | +- **`devel`** (default): all development and PRs. Version carries a `.9000` |
| 11 | + suffix; NEWS.md starts with `# pdp (development version)`. |
| 12 | +- **`main`**: stable releases only, tagged `vX.Y.Z`. r-universe |
| 13 | + (pinned to main in bgreenwell/bgreenwell.r-universe.dev) and the pkgdown |
| 14 | + site both build from main — never push experimental work there. |
| 15 | +- Release: merge devel → main, drop the `.9000` suffix and dev NEWS heading, |
| 16 | + tag, push; then bump devel to the next `.9000`. |
| 17 | +- Shared fixes that main needs immediately (CI, README): commit to **main |
| 18 | + first, then merge main → devel**. Never cherry-pick devel → main — it |
| 19 | + duplicates commits and makes main appear "ahead" of devel. |
| 20 | + |
| 21 | +## Dependency philosophy |
| 22 | + |
| 23 | +Keep Imports minimal: `graphics, grDevices, lattice, methods, stats, tinyplot, |
| 24 | +utils` — nothing else without strong justification. Plotting is |
| 25 | +**tinyplot** (zero-dep base graphics), *not* ggplot2 (removed in 0.9.0). |
| 26 | +`foreach` lives in Suggests and is only touched when `parallel = TRUE` |
| 27 | +(see `par_loop()` in `R/pardep.R`). Use `pkg::fun()` for Suggests packages. |
| 28 | + |
| 29 | +## Commands |
| 30 | + |
| 31 | +```bash |
| 32 | +Rscript -e 'devtools::document()' # after roxygen edits |
| 33 | +Rscript -e 'pkgload::load_all("."); tinytest::run_test_dir("inst/tinytest")' # full test suite |
| 34 | +Rscript -e 'devtools::check()' # before pushing |
| 35 | +``` |
| 36 | + |
| 37 | +Tests use **tinytest** (not testthat) in `inst/tinytest/`. Model-specific |
| 38 | +tests (`test_pkg_*.R`) are gated behind `at_home()` and skip on CRAN-style |
| 39 | +checks. Always add a NEWS.md entry; never edit `man/` by hand. |
| 40 | + |
| 41 | +## Architecture (R/) |
| 42 | + |
| 43 | +- `partial.R` — `partial()` orchestrator: extracts training data, builds the |
| 44 | + grid, dispatches to the compute engine, optionally plots. |
| 45 | +- `pardep.R` — brute-force engine. One unified loop; `batch.size` stacks grid |
| 46 | + points per `predict()` call (fast path); `par_loop()` = lapply or foreach. |
| 47 | + `pardep_gbm()` calls the C++ recursive method (`src/PartialGBM.cpp`). |
| 48 | +- `get_predictions.R` — per-model `get_predictions()` / `get_probs()` S3 |
| 49 | + wrappers; probability→output goes through `finalize_probs()`. Identical |
| 50 | + methods are aliased (e.g., `get_probs.qda <- get_probs.lda`). |
| 51 | +- `get_task.R` / `get_training_data.R` — infer regression vs. classification; |
| 52 | + recover training data from the model call. |
| 53 | +- `pred_grid.R` — grid construction (`grid.resolution`, `quantiles`, |
| 54 | + `trim.outliers`, `cats`). |
| 55 | +- `plot.R` — tinyplot engine (`plot.partial/ice/cice`); `plotPartial.R` — |
| 56 | + lattice engine; `utils.R` — ICE centering/averaging, `multiclass_logit()`. |
| 57 | + |
| 58 | +## Supporting a new model class |
| 59 | + |
| 60 | +1. `get_task.newclass()` in `R/get_task.R` (or rely on `type` arg). |
| 61 | +2. `get_predictions.newclass()` and/or `get_probs.newclass()` (funnel through |
| 62 | + `finalize_probs()`); `get_training_data.newclass()` only if the default |
| 63 | + call-recovery fails. |
| 64 | +3. Add `inst/tinytest/test_pkg_newclass.R`; add the package to Suggests. |
| 65 | + |
| 66 | +## Gotchas |
| 67 | + |
| 68 | +- **gbm recursive method (C++)**: factor grid columns must be converted to |
| 69 | + **0-based** integer codes before `.Call("PartialGBM", ...)`; `data.matrix()` |
| 70 | + alone gives 1-based codes and silently corrupts results (bug fixed in |
| 71 | + 0.9.0 — keep `test_pkg_gbm.R`'s recursive-vs-brute-force comparison green). |
| 72 | +- **tinyplot lazily evaluates some args** (e.g., `legend`) in another |
| 73 | + environment, and records calls for `tinyplot_add()`. Build internal tinyplot |
| 74 | + calls with `do.call()` so stored calls contain values, never `...`. |
| 75 | +- `batch.size` requires one prediction per row of `newdata`; incompatible |
| 76 | + with aggregating `pred.fun`s (informative error exists). |
| 77 | +- `partial(plot = TRUE)` draws via tinyplot and returns data invisibly; |
| 78 | + `plot.engine = "lattice"` returns a trellis object instead. |
| 79 | + |
| 80 | +## CI / site |
| 81 | + |
| 82 | +GitHub Actions (r-lib/actions v2): R-CMD-check + test-coverage on pushes/PRs |
| 83 | +to main and devel; pkgdown builds from **main only** and deploys to |
| 84 | +`gh-pages` (served at https://bgreenwell.github.io/pdp/). Vignettes are plain |
| 85 | +Rmd in `vignettes/` and run at build time — keep their chunks fast. |
0 commit comments