Error calling lmFit (limma) in an R package - r

I am including a call to lmFit in a new-private R package. But when calling the method that includes the call to lmFit I got an error:
Error in getEAWP(object) : could not find function "exprs"
The implemented structure follows:
setMethod(
f = "genexp",
signature = "clusterContainer",
definition = function(object, expSet, fdr.cutoff = 0.05) {
design <- model.matrix(groups, data = Biobase::pData(expSet))
fit <- limma::lmFit(expSet, design)
fit <- limma::eBayes(fit)
# [...]
}
)
The DESCRIPTION file contains:
...
LazyData: true
Imports:
Biobase,
...
limma
Suggests:
testthat
And the NAMESPACE:
exportPattern("^[^\\.]")
importFrom(Biobase, AnnotatedDataFrame)
importFrom(Biobase, exprs)
What I need to do to call lmFit (and others) and let them use functionality of third packages?
UPDATE 1: I add the traceback:
> genexp(c, expression)
Error in getEAWP(object) : could not find function "exprs"
5 getEAWP(object)
4 limma::lmFit(expSet, design) at clusterContainer-genexp.R#18
3 .local(object, ...)
2 genexp(c, expression) at 1_AllGenerics.R#50
1 genexp(c, expression)
UPDATE 2: The function getEAWP is from limma. The function exprs is from Biobase.

Related

Function passes test inside the package and fails from vignette (due to cpp_object_initializer)

I am writing an R package that uses rstan for Bayesian
sampling. (Here
is the specific commit if you want to reproduce the issue.) I only succeed in
running a function that calls rstan from the vignette if I use
library(rstan) in the vignette, and not with a few workarounds.
The setup
A function in the package calls rstan (edited for clarity):
#' #importFrom Rcpp cpp_object_initializer
#' #export
run_variational_bayes <- function(x, y, output_samples, beta_sd, stan_file) {
n_input <- length(y)
p <- ncol(x)
train_dat <- list(n = n_input, p = p, x = x, y = y, beta_sd = beta_sd)
stan_model <- rstan::stan_model(file = stan_file)
stan_vb <- rstan::vb(object = stan_model, data = train_dat,
output_samples = output_samples)
return(rstan::extract(stan_vb)$beta)
}
I test this function in the package:
context("RStan variational Bayes model")
test_that("Rstan variational Bayes model runs", {
german <- PosteriorBootstrap::get_german_credit_dataset()
n_bootstrap <- 10
prior_variance <- 100
stan_vb_sample <- PosteriorBootstrap::run_variational_bayes(x = german$x,
y = german$y,
output_samples = n_bootstrap,
beta_sd = sqrt(prior_variance),
iter = 10)
expect_true(nrow(stan_vb_sample) == n_bootstrap)
expect_true(ncol(stan_vb_sample) == ncol(german$x))
})
The tests pass locally and on Travis, so the function works from inside the
package.
The problem
The vignette code works if I include library(rstan):
library(rstan)
prior_sd <- 10
n_bootstrap <- 1000
german <- PosteriorBootstrap::get_german_credit_dataset()
stan_vb_sample <- PosteriorBootstrap::run_variational_bayes(x = german$x,
y = german$y,
output_samples = n_bootstrap,
beta_sd = prior_sd)
dim(stan_vb_sample)
#> [1] 1000 25
but I see it as bad practice that the user needs to attach another package to
use my package. If I use requireNamespace(), building the vignette works but
the Stan model does not run:
requireNamespace("PosteriorBootstrap", quietly = TRUE)
# ...
stan_vb_sample <- PosteriorBootstrap::run_variational_bayes(x = german$x,
y = german$y,
output_samples = n_bootstrap,
beta_sd = prior_sd)
#> Error in cpp_object_initializer(.self, .refClassDef, ...) :
#> could not find function "cpp_object_initializer"
#> failed to create the model; variational Bayes not done
#> Stan model 'bayes_logit' does not contain samples.
dim(stan_vb_sample)
#> NULL
Note that I used #' #importFrom Rcpp cpp_object_initializer in the Roxygen
comment, which should import the function that rstan says is missing.
Comparison with another package that uses rstan
This package
has similar values in DESCRIPTION, yet I tested that it does not require library(rstan) to
run rstan. It uses #import Rcpp in one function, which I tested with my
package by replacing #importFrom Rcpp cpp_object_initializer in front of the
function and got the same error.
Failed workarounds
The difference between requireNamespace() and library() is that the latter
imports the namespace of the package into the current environment. But
rstan does import(Rcpp) so that object should be available.
(1) I tried library("PosteriorBootstrap") in the vignette, since the
package imports that object into its namespace: I got the same error (with
#import Rcpp or with #importFrom Rcpp cpp_object_initializer).
(2) I copied that object to the environment of the function:
requireNamespace("Rcpp", quietly = TRUE)
#' #import Rcpp
#' #export
run_variational_bayes <- function(x, y, output_samples, beta_sd,
stan_file = get_stan_file(),
iter = 10000, seed = 123, verbose = FALSE) {
cpp_object_initializer <- Rcpp:cpp_object_initializer
# ...
}
and I was surprised to get a vignette error:
E creating vignettes (1.8s)
Quitting from lines 151-157 (anpl.Rmd)
Error: processing vignette 'anpl.Rmd' failed with diagnostics:
object 'Rcpp' not found
Execution halted
Temporary solution
As a temporary solution, I moved the code in the function to the vignette
entirely. The vignette fails with requireNamespace():
requireNamespace("rstan")
#> Loading required namespace: rstan
prior_sd <- 10
n_bootstrap <- 1000
german <- PosteriorBootstrap::get_german_credit_dataset()
train_dat <- list(n = length(german$y), p = ncol(german$x), x = german$x, y = german$y, beta_sd = prior_sd)
stan_file <- PosteriorBootstrap::get_stan_file()
stan_model <- rstan::stan_model(file = stan_file)
stan_vb <- rstan::vb(object = stan_model, data = train_dat, seed = seed,
output_samples = n_bootstrap)
#> Error in cpp_object_initializer(.self, .refClassDef, ...) :
#> could not find function "cpp_object_initializer"
#> failed to create the model; variational Bayes not done
stan_vb_sample <- rstan::extract(stan_vb)$beta
#> Stan model 'bayes_logit' does not contain samples.
dim(stan_vb_sample)
#> NULL
and succeeds with library(rstan):
library("rstan")
#> Loading required package: ggplot2
# ...
stan_model <- rstan::stan_model(file = stan_file)
stan_vb <- rstan::vb(object = stan_model, data = train_dat, seed = seed,
output_samples = n_bootstrap)
#> Chain 1: ------------------------------------------------------------
# ...
#> Chain 1: COMPLETED.
stan_vb_sample <- rstan::extract(stan_vb)$beta
dim(stan_vb_sample)
#> [1] 1000 25
In moving the code out of the package, I realised that a test that uses
library("rstan") and calls the rstan package directly, e.g.
context("Adaptive non-parametric learning function")
library("rstan")
# ...
test_that("Adaptive non-parametric learning with posterior samples works", {
german <- get_german_credit_dataset()
n_bootstrap <- 100
# Get posterior samples
seed <- 123
prior_sd <- 10
train_dat <- list(n = length(german$y), p = ncol(german$x), x = german$x,
y = german$y, beta_sd = prior_sd)
stan_model <- rstan::stan_model(file = get_stan_file())
stan_vb <- rstan::vb(object = stan_model, data = train_dat, seed = seed,
output_samples = n_bootstrap)
stan_vb_sample <- rstan::extract(stan_vb)$beta
# ...
}
passes the tests inside the package:
✔ | 24 | Adaptive non-parametric learning function [53.1 s]
══ Results ═════════════════════════════════════════════════════════════════════
Duration: 53.2 s
OK: 24
Failed: 0
Warnings: 0
Skipped: 0
but the same test with requireNamespace("rstan") fails them:
⠋ | 21 | Adaptive non-parametric learning functionError in cpp_object_initializer(.self, .refClassDef, ...) :
could not find function "cpp_object_initializer"
Stan model 'bayes_logit' does not contain samples.
...
══ Results ═════════════════════════════════════════════════════════════════════
Duration: 51.7 s
OK: 22
Failed: 1
Warnings: 0
Skipped: 0
Conclusion
I wonder if rstan code is calling cpp_object_initializer without a
qualifier, and if it's doing that in a new environment that does not inherit the
objects from the calling environment.
I acknowledge that I did not use rstantools to start the package
(my employer decided to stick with the MIT license and chose not to restart the
package structure from scratch) and that I am compiling
the model at call time. I suppose that users providing their own model would
face the same errors when using requireNamespace() instead of library().
How can I allow users to run package functions that call rstan without
library(rstan), short of restarting the package from scratch with rstantools?

devtools::check fails with cpp_object_initializer

I run devtools::test and it works:
$ RScript -e "devtools::test()"
...
OK: 24
But devtools::check fails at a test:
$ RScript -e "devtools::check()"
...
> test_check("package")
Error in cpp_object_initializer(.self, .refClassDef, ...) :
could not find function "cpp_object_initializer"
Stan model 'bayes_logit' does not contain samples.
── 1. Error: Mixture of Dirichlet Processes stick-breaking works and returns (#t
'data' must be of a vector type, was 'NULL'
1: mdp_logit_mvn_stickbreaking(n_samp = n_samp, mix_mean = NULL, mix_cov = NULL, posterior_sample = stan_sample,
prior_sample_size = 1, dataset = german, tol = 1e-08) at testthat/test_stick_breaking.R:35
2: MASS::mvrnorm(n = n_samp, mu = mix_mean, Sigma = mix_cov)
3: eigen(Sigma, symmetric = TRUE)
4: unname(as.matrix(x))
5: as.matrix(x)
6: as.matrix.default(x)
7: array(x, c(length(x), 1L), if (!is.null(names(x))) list(names(x), NULL) else NULL)
How can I fix it?
This is due to the difference between loading and attaching. I took the solution from this GitHub issue.
Add this in NAMESPACE to tell R where to find cpp_object_initialiser:
Depends:
Rcpp
This works, but it gives you a note. To avoid the note, add an Roxygen export around the function that uses the Rstan call:
#' #importFrom Rcpp cpp_object_initializer
function_name <- function(...) {...}

dplyr clashes with testthat package when matches is used

I am getting an error because testthat::matches clashes with dplyr::matches, and I want to know how to use testthat::test_file to check functions which contain calls to matches(), without having to specify dplyr::matches in the function body.
E.g.:
> testthat::test_file('tmp_fn_testthat_test.R')
Attaching package: ‘testthat’
The following object is masked from ‘package:dplyr’:
matches
The following object is masked from ‘package:purrr’:
is_null
Show Traceback
Rerun with Debug
Error in -matches("tmp") : invalid argument to unary operator In addition: Warning message:
package ‘testthat’ was built under R version 3.2.5
DONE =========================================================================================================================================
This error can be reproduced by saving the following code in a file called tmp_fn_testthat_test.R in your working directory, and running the command testthat::test_file('tmp_fn_testthat_test_20161115.R'). Note that sourcing or running the expect_equal command while testthat is not loaded makes the test pass.
tmp_fn <- function() {
tmp_df <- data.frame(tmp_a = 1, tmp_b = 2)
tmp_df %>%
select(-matches('tmp')) %>%
ncol
}
testthat::expect_equal(tmp_fn(), 0)
This is a known issue with dplyr 0.5. The recommended solution is to use an explicit namespace prefix: dplyr::matches.
A work around appears to be commenting out the library(testthat) in the definition of testthat::test_file, and making function calls explicit (not sure whether this will have bad side effects):
my_test_that_file <- function (path, reporter = "summary", env = testthat::test_env(), start_end_reporter = TRUE,
load_helpers = TRUE)
{
# library(testthat)
reporter <- testthat:::find_reporter(reporter)
if (load_helpers) {
testthat:::source_test_helpers(dirname(path), env = env)
}
lister <- testthat:::ListReporter$new()
if (!is.null(reporter)) {
reporter <- testthat:::MultiReporter$new(reporters = list(reporter,
lister))
}
else {
reporter <- lister
}
testthat::with_reporter(reporter = reporter, start_end_reporter = start_end_reporter,
{
lister$start_file(basename(path))
testthat::source_file(path, new.env(parent = env), chdir = TRUE)
testthat:::end_context()
})
invisible(lister$get_results())
}

Is it possible to call S4 method directly?

Trying to build a gausspr model and using predict to predict the output. Copying code from predict.gausspr documentation.
data(promotergene)
## create test and training set
ind <- sample(1:dim(promotergene)[1],20)
genetrain <- promotergene[-ind, ]
genetest <- promotergene[ind, ]
## train a support vector machine
gene <- gausspr(Class~.,data=genetrain,kernel="rbfdot",
kpar=list(sigma=0.015))
## predict gene type probabilities on the test set
genetype <- predict(gene,genetest,type="probabilities")
This works fine. Now, when i try to call predict.gausspr directly it's failing. Is it possible to call this S4 method directly ?
Also, is this case with any S4 method or something special in this case ?
> genetype <- predict.gausspr(gene,genetest,type="probabilities")
Error: could not find function "predict.gausspr"
kernlab package is loaded properly and am able to do ?predict.gausspr and see the notes
I guess you mean the gausspr() function from the kernlab package. Using the snippet from ?gausspr I see
library(kernlab)
data(iris)
test <- gausspr(Species~., data=iris, var=2)
predict(test, iris[,-5])
test is indeed an S4 object
> isS4(test)
[1] TRUE
> class(test)
[1] "gausspr"
attr(,"package")
[1] "kernlab"
Discovering S4 methods
S4 methods are discovered using showMethods() and selectMethod() (output edited for brevity)
> showMethods("predict")
Function: predict (package stats)
object="ANY"
object="gausspr"
object="kfa"
object="kha"
object="kpca"
object="kqr"
object="ksvm"
object="lssvm"
object="onlearn"
object="rvm"
> showMethods(class=class(test), where=search())
Function: alphaindex (package kernlab)
object="gausspr"
...
Function: predict (package stats)
object="gausspr"
...
> selectMethod("predict", class Method Definition:
function (object, ...)
{
.local <- function (object, newdata, type = "response", coupler = "minpair")
{
sc <- 0
type <- match.arg(type, c("response", "probabilities",
"votes", "variance"))
...
If there was no relevant predict,gausspr method, then we would end up at predict,ANY-method, which actually invokes the S3 methods discovered by methods("predict").
The help page is discovered with
?"predict,gausspr-method"
Debugging S4 methods
traceback / recover
If a method fails and you'd like to debug it, then usually the simplest thing to do is to use ?traceback to find out where the error occurs, and ?recover to identify the problem in more detail. Here's an error
> predict(test, mtcars)
Error in eval(expr, envir, enclos) : object 'Sepal.Length' not found
and we can see the 'call stack' from 1 (the generic 'predict') to 2 (the method 'predict,gausspr-mehtod') to 3 (the .local function, defined inside the gausspr method), etc.
> traceback()
9: eval(expr, envir, enclos)
8: eval(predvars, data, env)
7: model.frame.default(object, data, xlev = xlev)
6: model.frame(object, data, xlev = xlev)
5: model.matrix.default(delete.response(terms(object)), as.data.frame(newdata),
na.action = na.action)
4: model.matrix(delete.response(terms(object)), as.data.frame(newdata),
na.action = na.action)
3: .local(object, ...)
2: predict(test, mtcars)
1: predict(test, mtcars)
Set the error option (see ?options) to recover and try again, choosing the frame number inside the .local function to be in the body of the method.
> options(error=recover)
> predict(test, mtcars)
Error in eval(expr, envir, enclos) : object 'Sepal.Length' not found
Enter a frame number, or 0 to exit
1: predict(test, mtcars)
2: predict(test, mtcars)
3: .local(object, ...)
4: model.matrix(delete.response(terms(object)), as.data.frame(newdata), na.act
5: model.matrix.default(delete.response(terms(object)), as.data.frame(newdata)
6: model.frame(object, data, xlev = xlev)
7: model.frame.default(object, data, xlev = xlev)
8: eval(predvars, data, env)
9: eval(expr, envir, enclos)
Selection: 3
Called from: eval(predvars, data, env)
Browse[1]> ls()
[1] "coupler" "ncols" "newdata" "nrows" "object" "oldco" "sc"
[8] "type"
Restore normal error behavior with options(error=NULL).
debug / trace
There are a couple of things to do to debug S4 methods. The first is to use the debugger on the selected methods
debug(selectMethod("predict", class(test)))
The second is to trace the method
trace("predict", browser, signature=class(test))
(stop tracing with untrace("predict", signature=class(test))
In this particular case you'll see that the body of the function is in a nested function called .local. Setting the debugger on the outer function is not enough, instead one needs to break in the outer function, then step through until .local has been defined but not evaluated, and set the debugger on .local, like (editing the output for brevity)
> trace(predict, browser, signature=class(test))
Tracing specified method for function "predict" in environment
<namespace:stats>
Warning: Tracing only in the namespace; to untrace you will need:
untrace("predict", where = getNamespace("stats"))
[1] "predict"
attr(,"package")
[1] "stats"
> predict(test, iris[,-5])
Tracing predict(test, iris[, -5]) on entry
Called from: eval(expr, envir, enclos)
Browse[1]> n
debug: {
.local <- function (object, newdata, type = "response", coupler = "minpair")
{
sc <- 0
type <- match.arg(type, c("response", "probabilities",
...
Browse[2]> n
debug: .local(object, ...)
Browse[2]> debug(.local)
Browse[2]> n
debugging in: .local(object, ...)
debug: {
sc <- 0
type <- match.arg(type, c("response", "probabilities", "votes",
...
Browse[3]>
The author of the kernlab package did not provide an S3-style function predict.gausspr, even though the S4 guidelines (?setMethod) suggest that they do. This would have simplified debugging, e.g., debug(kernlab:::predict.gausspr).

Why can't I vectorize source_url in knitr?

I am trying to vectorize this call to source_url, in order to load some functions from GitHub:
library(devtools)
# Find ggnet functions.
fun = c("ggnet.R", "functions.R")
fun = paste0("https://raw.github.com/briatte/ggnet/master/", fun)
# Load ggnet functions.
source_url(fun[1], prompt = FALSE)
source_url(fun[2], prompt = FALSE)
The last two lines should be able to work in a lapply call, but for some reason, this won't work from knitr: to have this code work when I process a Rmd document to HTML, I have to call source_url twice.
The same error shows up with source_url from devtools and with the one from downloader: somehwere in my code, an object of type closure is not subsettable.
I suspect that this has something to do with SHA; any explanation would be most welcome.
It has nothing to do with knitr or devtools or vectorization. It is just an error in your(?) code, and it is fairly easy to find it out using traceback().
> library(devtools)
> # Find ggnet functions.
> fun = c("ggnet.R", "functions.R")
> fun = paste0("https://raw.github.com/briatte/ggnet/master/", fun)
> # Load ggnet functions.
> source_url(fun[1], prompt = FALSE)
SHA-1 hash of file is 2c731cbdf4a670170fb5298f7870c93677e95c7b
> source_url(fun[2], prompt = FALSE)
SHA-1 hash of file is d7d466413f9ddddc1d71982dada34e291454efcb
Error in df$Source : object of type 'closure' is not subsettable
> traceback()
7: which(df$Source == x) at file34af6f0b0be5#14
6: who.is.followed.by(df, "JacquesBompard") at file34af6f0b0be5#19
5: eval(expr, envir, enclos)
4: eval(ei, envir)
3: withVisible(eval(ei, envir))
2: source(temp_file, ...)
1: source_url(fun[2], prompt = FALSE)
You used df in the code, and df is a function in the stats package (density of the F distribution). I know you probably mean a data frame, but you did not declare that in the code.

Resources