devtools::check fails with cpp_object_initializer - r

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(...) {...}

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?

How to capture particular warning message and execute call

Lately when I run my code that uses coxph in the survival package
coxph(frml,data = data), I am now getting warning messages of the following type
1: In model.matrix.default(Terms, mf, contrasts = contrast.arg) :
partial argument match of 'contrasts' to 'contrasts.arg'
2: In seq.default(along = temp) :
partial argument match of 'along' to 'along.with'"
I'm not exactly sure why all of a sudden these partial argument match warnings started popping up, but I don't think they effect me.
However, when I get the following warning message, I want coxph(frml,data = data) = NA
3: In fitter(X, Y, strats, offset, init, control, weights = weights, :
Loglik converged before variable 2 ; beta may be infinite.
6: In coxph(frml, data = data) :
X matrix deemed to be singular; variable 1 3 4
I used tryCatch when I wasn't getting the partial argument match warning using this code where if the nested tryCatch got either a warning or error message it would return NA
coxphfit = tryCatch(tryCatch(coxph(frml,data = data), error=function(w) return(NA)), warning=function(w) return(NA))
However, now that I am getting the partial argument match warnings, I need to only return an NA if there is an error or if I get the above warning messages 3 and 4 . Any idea about how to capture these particular warning messages and return an NA in those instances?
It's actually interesting question, if you are looking for quick and dirty way of capturing warnings you could simply do:
withCallingHandlers({
warning("hello")
1 + 2
}, warning = function(w) {
w ->> w
}) -> res
In this example the object w created in parent environment would be:
>> w
<simpleWarning in withCallingHandlers({ warning("hello") 1 + 2}, warning = function(w) { w <<- w}): hello>
You could then interrogate it:
grepl(x = w$message, pattern = "hello")
# [1] TRUE
as
>> w$message
# [1] "hello"
Object res would contain your desired results:
>> res
[1] 3
It's not the super tidy way but I reckon you could always reference object w and check if the warning message has the phrase you are interested in.

Error calling lmFit (limma) in an R package

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.

R: annotate() gives error in R

I am new to R. I have to use POSTagger in my code. I am using openNLP with R. While trying following sample code (in Sample.R file):
library("NLP")
library("openNLP")
s <- paste(c("Pierre Vinken, 61 years old, will join the board as a ",
"nonexecutive director Nov. 29.\n",
"Mr. Vinken is chairman of Elsevier N.V., ",
"the Dutch publishing group."),
collapse = "")
s <- as.String(s)
sent_token_annotator <- Maxent_Sent_Token_Annotator()
a1 <- annotate(s, sent_token_annotator)
s[a1]
And running this code from R Console (Using source("Sample.R"))
I am getting following error:
Error in as.data.frame.default(x[[i]], optional = TRUE) :
cannot coerce class "c("Simple_POS_Tag_Annotator", "Annotator")" to a data.frame
Following is the output of traceback() command :
14: stop(gettextf("cannot coerce class \"%s\" to a data.frame", deparse(class(x))),
domain = NA)
13: as.data.frame.default(x[[i]], optional = TRUE)
12: as.data.frame(x[[i]], optional = TRUE)
11: data.frame(x = function (s, a = Annotation())
{
s <- as.String(s)
y <- f(s)
n <- length(y)
id <- .seq_id(next_id(a$id), n)
type <- rep.int("sentence", n)
if (is.Annotation(y)) {
y$id <- id
y$type <- type
}
else if (is.Span(y)) {
y <- as.Annotation(y, id = id, type = type)
}
else stop("Invalid result from underlying sentence tokenizer.")
if (length(i <- which(a$type == "paragraph"))) {
a <- a[i]
a$features <- lapply(annotations_in_spans(y, a), function(e) list(constituents = e$id))
y <- c(y, a)
}
y
}, check.names = FALSE, stringsAsFactors = FALSE)
10: eval(expr, envir, enclos)
9: eval(as.call(c(expression(data.frame), x, check.names = !optional,
stringsAsFactors = stringsAsFactors)))
8: as.data.frame.list(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors)
7: as.data.frame(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors)
6: data.frame(position)
5: annotate(s, sent_token_annotator) at sample.R#11
4: eval(expr, envir, enclos)
3: eval(ei, envir)
2: withVisible(eval(ei, envir))
1: source("sample.R")
What can be possibly wrong? I am using Rx64 3.1.1 on Windows 7. Any help will be much appreciated. Thanks in advance.
I have the same problem and i fixed it by removing/detach the ggplot2 package. There is a function called Annotate in ggplot2 and it is the same name in both packages. I suggest you make sure that it is looking at the correct function in the library... in my case it was looking at the Annotate function of ggplot2 and not the NLP package.
I don't have an exact answer but suffered the same error using NLP, openNLP, tm, qdap. I worked backward restarting R and loading (library) one package, running code, then loading another package and running code, until I ran across the "cannot coerce to a dataframe" error. I found, in my case that qdap interferes with the openNLP annotate() function call -- which is actually using an NLP wrapper.
openNLP version 0.2-3 imports NLP (≥ 0.1-2), openNLPdata (≥ 1.5.3-1), and rJava (≥ 0.6-3). Because you loaded NLP explicitly, it may be a case of two instances of NLP running in memory interfering with each other. Try just loading openNLP and running your code
Multiple packages have same name. If you specifically tell R which package to use it will probably resolve the issue. For example, instead of Arrange(...), try using openNLP::Arrange(...)

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