Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ Authors@R:
Description: Filter, wrapper, and embedded feature-selection methods behind a
consistent set of functions that share one calling convention and one
return type: univariate threshold filters, correlation and chi-squared
filters, information gain, LASSO and elastic net, Bayesian model
comparison, Boruta, recursive feature
elimination, random forest importance, multivariate adaptive regression
splines, support vector machine recursive feature elimination, stepwise
selection, and principal component / singular value decomposition
helpers. The implemented methods follow
filters, information gain, the least absolute shrinkage and selection
operator (LASSO) and elastic net, Bayesian model comparison, Boruta,
recursive feature elimination, random forest importance, multivariate
adaptive regression splines, support vector machine recursive feature
elimination, stepwise selection, and principal component / singular
value decomposition helpers. The implemented methods follow
Tibshirani (1996) <doi:10.1111/j.2517-6161.1996.tb02080.x>,
Zou and Hastie (2005) <doi:10.1111/j.1467-9868.2005.00503.x>,
Friedman (1991) <doi:10.1214/aos/1176347963>,
Expand All @@ -35,7 +35,7 @@ Imports:
parallel,
stats,
utils,
withr
withr (>= 2.4.0)
Suggests:
bigstatsr,
Boruta,
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ documentation page found and fixed silent wrong answers, hangs, crashes, and
inaccurate claims. Fixes that change behavior are listed first under each
review. Where a result changed, the old result was wrong.

* featR now requires withr 2.4.0 or later, the first release that exports
`local_seed()`.
* Examples that run in under two seconds are no longer wrapped in
`\donttest{}`, so `R CMD check` runs them.

## First adversarial review

A full statistical, methodological, and programmatic review. Every finding
Expand Down
8 changes: 3 additions & 5 deletions R/fs_elastic.R
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,6 @@ elastic_check_categorical_levels <- function(data, predictors) {
#' `use_pca = TRUE`).}
#' \item{call}{The matched call.}
#' @examples
#' \donttest{
#' if (requireNamespace("caret", quietly = TRUE) &&
#' requireNamespace("glmnet", quietly = TRUE) &&
#' requireNamespace("Matrix", quietly = TRUE)) {
Expand All @@ -672,10 +671,9 @@ elastic_check_categorical_levels <- function(data, predictors) {
#' )
#' df$y <- 2 * df$x1 - df$x2 + 0.1 * cos(seq_len(60) * 3)
#' res <- fs_elastic(df, "y", alpha_seq = c(0.5, 1), seed = 1)
#' selected(res)
#' res$scores
#' res$details$best_alpha
#' }
#' print(selected(res))
#' print(res$scores)
#' print(res$details$best_alpha)
#' }
#' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html)
#' guide, which runs this function on a worked example.
Expand Down
6 changes: 2 additions & 4 deletions R/fs_lasso.R
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,6 @@ lasso_importance <- function(coefs) {
#' and `n_features` (number of design-matrix columns considered).}
#' \item{call}{The matched call.}
#' @examples
#' \donttest{
#' if (requireNamespace("glmnet", quietly = TRUE)) {
#' n <- 100
#' df <- data.frame(
Expand All @@ -541,9 +540,8 @@ lasso_importance <- function(coefs) {
#' )
#' df$y <- 2 * df$x1 - 3 * df$x2 + rnorm(n)
#' res <- fs_lasso(df, "y", seed = 123)
#' selected(res)
#' head(res$scores)
#' }
#' print(selected(res))
#' print(head(res$scores))
#' }
#' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html)
#' guide, which runs this function on a worked example.
Expand Down
8 changes: 3 additions & 5 deletions R/fs_mars.R
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,6 @@ mars_evaluate <- function(model, test, target, verbose = FALSE) {
#' }
#'
#' @examples
#' \donttest{
#' if (requireNamespace("caret", quietly = TRUE) &&
#' requireNamespace("earth", quietly = TRUE)) {
#' # x1 and x2 drive y; x3 is noise
Expand All @@ -745,10 +744,9 @@ mars_evaluate <- function(model, test, target, verbose = FALSE) {
#' df$y <- 2 * df$x1 - df$x2 + rnorm(150, sd = 0.5)
#' res <- fs_mars(df, "y", degree = 1, nprune = c(5, 10),
#' number = 3, repeats = 1, seed = 42)
#' res$selected
#' res$scores
#' res$details$metrics
#' }
#' print(res$selected)
#' print(res$scores)
#' print(res$details$metrics)
#' }
#' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html)
#' guide, which runs this function on a worked example.
Expand Down
2 changes: 0 additions & 2 deletions R/fs_pca.R
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,6 @@ pca_plot <- function(pca_result, label_col) {
#' res$var_explained
#' head(res$pca_df)
#'
#' \donttest{
#' if (requireNamespace("ggplot2", quietly = TRUE)) {
#' # plot = FALSE (the default) draws nothing, but $plot is built anyway
#' res <- fs_pca(iris, label_col = "Species", verbose = TRUE)
Expand All @@ -503,7 +502,6 @@ pca_plot <- function(pca_result, label_col) {
#' # plot = TRUE draws it as well
#' res <- fs_pca(iris, label_col = "Species", plot = TRUE)
#' }
#' }
#' @seealso The [Dimensionality reduction](https://elkronos.github.io/featR/articles/dimensionality-reduction.html)
#' guide, which runs this function on a worked example.
#' @export
Expand Down
2 changes: 0 additions & 2 deletions R/fs_randomforest.R
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ rf_pool_importance_sd <- function(forests) {
#' }
#'
#' @examples
#' \donttest{
#' if (requireNamespace("randomForest", quietly = TRUE) &&
#' requireNamespace("caret", quietly = TRUE)) {
#' res <- fs_randomforest(
Expand All @@ -416,7 +415,6 @@ rf_pool_importance_sd <- function(forests) {
#' print(res$scores)
#' print(res$details$metrics)
#' }
#' }
#' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html)
#' guide, which runs this function on a worked example.
#' @export
Expand Down
2 changes: 0 additions & 2 deletions R/fs_recursivefeature.R
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,6 @@ rfe_train_final <- function(data_df, target, optimal_vars,
#' }
#'
#' @examples
#' \donttest{
#' if (requireNamespace("caret", quietly = TRUE) &&
#' requireNamespace("randomForest", quietly = TRUE) &&
#' requireNamespace("e1071", quietly = TRUE)) {
Expand All @@ -839,7 +838,6 @@ rfe_train_final <- function(data_df, target, optimal_vars,
#' # the only held-out estimate on the object
#' print(res$details$test_metrics)
#' }
#' }
#' @seealso The [Wrapper methods](https://elkronos.github.io/featR/articles/wrappers.html)
#' guide, which runs this function on a worked example.
#' @export
Expand Down
2 changes: 0 additions & 2 deletions R/fs_stepwise.R
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,6 @@ step_term_scores <- function(model, coefs, term_labels) {
#' }
#'
#' @examples
#' \donttest{
#' if (requireNamespace("MASS", quietly = TRUE)) {
#' res <- fs_stepwise(mtcars, target = "mpg", direction = "both")
#' print(res$selected)
Expand All @@ -309,7 +308,6 @@ step_term_scores <- function(model, coefs, term_labels) {
#' refit <- stats::update(res$model, . ~ . - wt, data = mtcars)
#' print(stats::formula(refit))
#' }
#' }
#' @seealso The [Wrapper methods](https://elkronos.github.io/featR/articles/wrappers.html)
#' guide, which runs this function on a worked example.
#' @export
Expand Down
8 changes: 3 additions & 5 deletions R/fs_svm.R
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,6 @@ svm_performance <- function(predictions, actuals, task) {
#' \item{call}{The matched call.}
#' }
#' @examples
#' \donttest{
#' if (requireNamespace("caret", quietly = TRUE) &&
#' requireNamespace("kernlab", quietly = TRUE) &&
#' requireNamespace("e1071", quietly = TRUE)) {
Expand All @@ -1179,7 +1178,7 @@ svm_performance <- function(predictions, actuals, task) {
#' tune_grid = data.frame(C = 1),
#' seed = 42
#' )
#' res$details$performance
#' print(res$details$performance)
#'
#' # SVM-RFE keeps the two most useful measurements
#' sel <- fs_svm(
Expand All @@ -1194,9 +1193,8 @@ svm_performance <- function(predictions, actuals, task) {
#' n_features = 2,
#' seed = 42
#' )
#' sel$selected
#' sel$scores
#' }
#' print(sel$selected)
#' print(sel$scores)
#' }
#' @seealso The [Wrapper methods](https://elkronos.github.io/featR/articles/wrappers.html)
#' guide, which runs this function on a worked example.
Expand Down
62 changes: 40 additions & 22 deletions cran-comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,64 @@

This is an update of featR from 0.1.0 to 0.2.0.

It is a correctness release. Two statistical, methodological, and
programmatic reviews of the whole package fixed silent wrong answers, hangs,
crashes, and documentation that did not match behavior. Each fix has a
regression test; the test suite grew from 2013 to 2560 passing assertions.
It is a correctness release. A statistical, methodological, and programmatic
review of the whole package fixed silent wrong answers, hangs, crashes, and
documentation that did not match behavior. Each fix has a regression test.
Some fixes change results or turn previously accepted, invalid input into an
informative error. NEWS.md lists every change, with behavior changes first.

## Test environments

* GitHub Actions (r-lib/actions): macOS latest (R release), Windows latest
(R release), Ubuntu latest (R devel, R release, R oldrel-1).
* Ubuntu (R release) with every suggested package except Boruta, bigstatsr,
and PRROC installed: 2560 passing assertions, 7 skipped for those packages.
* win-builder (R devel).
* Local Ubuntu (R release), `R CMD check --as-cran` twice: once with every
suggested package installed and `--run-donttest`, and once with no
suggested packages installed (`_R_CHECK_FORCE_SUGGESTS_=false`), to confirm
that examples, tests, and the vignette all run without them.

## R CMD check results

0 errors | 0 warnings | 0 notes

* Words that may be flagged as possibly misspelled in DESCRIPTION (Barnhill,
Boruta, Gabry, Guyon, Hastie, Kursa, Rudnicki, Tibshirani, Vapnik, Vehtari,
Zou) are author surnames from the cited references and the name of the
Boruta method.

## Reverse dependencies

There are no reverse dependencies on CRAN.

## Notes for reviewers

* As requested in the review of 0.1.0, Boruta is no longer in single quotes
in the Description (it names the method), and the methods are cited as
authors (year) <doi:...>.
* All modeling engines (brms, caret, glmnet, randomForest, kernlab, earth,
Boruta, and others) are in Suggests. Every function that needs one checks
availability with `requireNamespace()` and fails with an informative message
naming the packages to install. All examples that use a suggested package are
wrapped in `\donttest{}` behind `requireNamespace()` guards, and the test
suite skips those paths when the package is absent.
* `fs_bayes()` compiles a Stan program per candidate model. Its example is in
`\donttest{}`, guarded on brms being installed, limited to two
single-predictor models, and wrapped in `try()`, so a machine without a
working Stan toolchain skips it rather than failing. The equivalent call is
exercised in the test suite under `skip_on_cran()`.
availability with `requireNamespace()` and stops with a message naming the
packages to install. Examples that use a suggested package are guarded with
`requireNamespace()`. The tests skip those paths when a package is absent.
* Examples run in under 2 seconds each and are not wrapped in `\donttest{}`,
with two exceptions. `fs_bayes()` compiles a Stan program per candidate
model; its example is in `\donttest{}`, guarded on brms, limited to two
single-predictor models, and wrapped in `try()` so that a machine without a
working Stan toolchain skips it rather than failing. `fs_boruta()` is in
`\donttest{}` because its run time depends on the number of Boruta
iterations.
* `fs_mars()` with `search = "random"` and a factor outcome attaches earth (a
suggested package) for the duration of that call with
`withr::local_package()`, because caret's random-grid code for earth looks
up `contr.earth.response` on the search path. On exit, earth and any
packages it attached are detached, so the user's search path is unchanged.
* Parallel execution is opt-in throughout. Every function defaults to a single
worker, requested worker counts are capped at the detected core count, and no
example or test uses more than two cores.
* The package never calls `set.seed()` unless the user supplies a `seed`
argument, and then restores the previous RNG state on exit via
`withr::local_seed()`.
* No package code writes to the user's file system, home directory, working
directory, or global environment.
worker, requested worker counts are capped at the detected core count, and
no example or test uses more than two cores.
* The package never seeds the random number generator unless the user
supplies a `seed` argument, and then restores the previous RNG state on exit
via `withr::local_seed()`.
* Package code writes nothing to the user's home directory, working
directory, or global environment. The only file it creates is a temporary
backing file under `tempdir()` for `fs_pca()` on very large data, which is
removed when the call returns.
Loading
Loading