Skip to contents

modifiedfisher 0.0.4

Performance

Internal optimisations to the modified_fisher_exact_test() pipeline; no results change.

  • optimise_gamma0() gained an optional .df argument and no longer rebuilds an identical test frame when the caller (modified_fisher_exact_test(), .accept()) already has one.
  • optimise_gamma0() and size_modified() now build the gamma0-independent part of the rejection matrix once and reuse it across their internal bisection/grid searches (via new internal helpers .build_rejection_base() and .finalize_rejection()), instead of rebuilding the full matrix at every candidate gamma0. .build_rejection_matrix() itself (used by local_size_modified(), power_modified(), and the gradient when not given a prebuilt matrix) is unchanged and remains a single self-contained builder, since those callers only ever need one gamma0 and gain nothing from the split.
  • size_modified()’s zoom-method grid search and the "trust" method’s initial scan now evaluate the whole candidate grid in one batched matrix computation instead of one function call per grid point.
  • .local_size_gradient_modified() (used by method = "trust") is vectorised - an exact rearrangement of the original nested-loop sum - and the "trust" method no longer rebuilds the rejection matrix on every evaluation.
  • power_modified() is rewritten from a nested loop over every table to the same bilinear-form reduction as local_size_modified(), including the superiority restriction, now applied as a precomputed mask rather than an inline condition.
  • Added internal batched-grid helpers .local_size_modified_grid() and .power_modified_grid(), used by the compute_size_curves() and compute_power_curves() example helpers in reproducing-paper-figures.Rmd to evaluate a whole grid of nuisance-parameter/response-rate values in one matrix computation instead of one function call per grid point.

optimise_gamma0(), size_modified(), and power_modified() gained new optional arguments (.df, .rejection_base / .rejection_matrix); all default to NULL and existing calls are unaffected.

Build

  • Fixed a broken .Rbuildignore pattern that let a stale knitr vignette cache leak into the built source tarball, causing an “over 100 bytes” tar portability warning from R CMD build.

Documentation

  • overview-of-algorithm.Rmd and reproducing-paper-figures.Rmd updated to describe the caching and vectorisation changes above, and their example helpers updated to use the new .df argument and the batched-grid helpers. The sample-size example in modifiedfisher.Rmd also passes .df to optimise_gamma0() now, for the same reason.

modifiedfisher 0.0.3

Consistent naming scheme for the five test variants

The comparator test functions have been renamed so that all five variants follow a single descriptive axis, instead of the earlier mix of an acronym (mfet), a software product (procfreq), and an author (woolf). Each variant is now named for its construction:

  • modified - the non-conservative, size-α modified Fisher exact test (this package’s test).
  • randomised - the fully randomised UMPU Fisher exact test.
  • conservative - the conservative, non-randomised Fisher exact test.
  • probability - the probability-method two-sided exact p-value (the p-value reported by SAS Proc FREQ).
  • asymptotic - Woolf’s asymptotic (Wald) test.

The size_*, local_size_*, and power_* families all use these suffixes, and file names have been updated to match. The exported and internal renames are:

Old name (v0.0.2) New name (v0.0.3)
size_mfet() size_modified()
local_size_mfet() local_size_modified()
local_size_woolf() local_size_asymptotic()
local_size_procfreq() local_size_probability()
power_mfet() power_modified()
power_woolf() power_asymptotic()
power_procfreq() power_probability()
pvalue_procfreq() pvalue_probability()
.mfet_reject() .modified_reject()
.local_size_gradient_mfet() .local_size_gradient_modified()

local_size_randomised(), power_randomised(), and power_conservative() were already on-scheme and are unchanged.

This is a breaking change: code written against the v0.0.2 comparator function names will need updating to the new names.

Documentation

  • Every exported function now documents its return value with @return (in v0.0.2 only the main function did), resolving the missing \value warning under R CMD check.
  • Replaced the placeholder \dontrun{} example on modified_fisher_exact_test() with a runnable example reproducing Example 1 of van der Meulen et al. (2021), and added a runnable @examples block to every exported helper.

CRAN readiness

  • Fixed the broken URL and BugReports links in DESCRIPTION (the repository is modifiedfisher, not modified-fisher).
  • Removed stray .DS_Store files and added them to .Rbuildignore.
  • Replaced non-ASCII characters in R source comments with ASCII equivalents.
  • Moved the Table 2 verification scripts (errata.R, check_table2_typos.R) out of inst/ and into a build-ignored data-raw/ directory.

modifiedfisher 0.0.2

This release is a major overhaul of the package structure, documentation, and test coverage relative to v0.0.1. The underlying statistical methodology is unchanged.

New exports

v0.0.1 exported only modified_fisher_exact_test(). The following diagnostic and comparison functions are now exported too:

  • construct_test_frame() - builds the full table of critical values and randomisation probabilities for each possible total T.
  • optimise_gamma0() - finds the optimal γ₀ threshold by bisection over the sorted randomisation probabilities.
  • size_mfet() - the local size of the modified Fisher exact test, maximised over the nuisance parameter.
  • local_size_mfet(), local_size_woolf(), local_size_procfreq(), local_size_randomised() - local size at a fixed nuisance parameter, for each of the four tests compared in van der Meulen et al. (2021).
  • power_mfet(), power_woolf(), power_procfreq(), power_randomised(), power_conservative() - power for each test at specified response rates.
  • pvalue_procfreq() - the SAS Proc FREQ-style conditional exact p-value.

Renamed functions and files

Internal functions have been renamed for consistency, and file names now match function names throughout. The main changes:

Old name New name
calc_exp_value .calc_expected_value
find_gamma .find_gamma12
local_size local_size_mfet
local_size_gradient .local_size_gradient_mfet
local_power / power_mfet power_mfet
mod_fe_test .mfet_reject
mod_fe_size / mfet_size size_mfet
sas_procfreq_pvalue pvalue_procfreq

Pure internal helpers are now dot-prefixed (.calc_expected_value, .find_gamma12, .mfet_reject, .accept, .build_rejection_matrix, .local_size_gradient_mfet) and carry @noRd, so they no longer appear in the help index.

Documentation

  • Updated the Title and Description fields in DESCRIPTION.
  • All exported functions gained roxygen documentation, with @param, @family, and @seealso cross-links.
  • Added a vignette (vignettes/modifiedfisher.Rmd).

Tests

Test coverage has grown from no test files to 7 (451 lines), covering .calc_expected_value, .find_gamma12, .mfet_reject, construct_test_frame, local_size_*, modified_fisher_exact_test, and power_mfet. The four worked examples from Table 2 of van der Meulen et al. (2021), accounting for the corrected types mentioned below, are included as regression tests in test-modified_fisher_exact_test.R.

A note on Table 2 in the source paper

While checking the package against those Table 2 examples, two typos were discovered in the published version. The package produces the correct numbers - it’s the printed table that’s off. Both were straightforward to confirm using closed-form Woolf limits and base R’s fisher.test(), neither of which relies on any package code.

  • Example 1 (5/12 vs 7/11): the lower CI limits dropped a leading zero. The modified test’s lower limit is 0.0716, not the printed “0.716” (and likewise Woolf’s is 0.076 not 0.760, and Proc FREQ’s is 0.055 not 0.550). The printed interval gives itself away, too: (0.716, 2.210) doesn’t contain its own point estimate of 0.408, which a test-based interval can’t do.
  • Example 4: printed as “72/128 vs 58/142”, but the numbers come from u = 71. Running it with u = 71 lines everything up - estimate 1.804, p-value 0.0175, CI (1.108, 2.936). With u = 72, nothing matches.
  • Examples 2 and 3 are fine as printed.

The tests use the corrected values.