package deployed function using SPECIAL characters (like %>%) - r

I've written a package (myHelpers) that had been using the following function:
#' Negate the \code{\%in\%} function.
#'
#' Use this for the OPPOSITE of \code{\%in\%}.
#'
#' #export
"%not in%" <- function(x, y) !x %in% y
In the past (last year) this worked fine with my package. But now (and I don't know why) with the following:
library(myHelpers)
df1 <- c(1,2,3,4,5)
df2 <- c(4,5)
df1 %not in% df2
Produced the following error:
Error in df1 %not in% df2 : could not find function "%not in%"
I don't know if something's changed when I build the package using roxygen2, but this is frustrating.
When I simple add this to my global environment in my session, everything is fine.
Any idea on how to get this function (with the SPECIAL characters of %) exported and seen with my myHelpers package would be appreciated.
Thanks,
Michael
EDIT 9-13-19 14:07 PST
I'm using RStudio and my shortcut to build the documentation (and the Namespace presumable) with Command+Shift+D. I'm assuming the documentation gets written as it's in the MAN folder for the package. BUT, I get this error in the Build pane:
Warning message:
roxygen2 requires Encoding: UTF-8
AND, when I look in the Namespace file, my function is missing (even tough I'm telling roxygen to export it (with the #export).
Looking for the fix...
EDIT 9-13-19 14:14 PST
FIXED
Added:
Encoding: UTF-8
To Description file...and I had an error that I didn't see. I was using:
#keyword export
Because I had been using #keyword internal for a bit with the function....Now, I changed it to the CORRECT:
#export
And I'm off and running. Thanks for helping with overtired academic discover his mistake.

Related

pkgdown fails parsing Rd files when examples are added

for some reason pkgdown is failing to parse one of the .Rd files that I have in my package. I found it fails when I add examples to the roxygen2 documentation using either the #examples tag or the #example inst/example/add.R alternative. I minimized my function to two arguments in order to make it more "reproducible" and still getting the same error. Please find bellow the error message, the .Rd file generated using that devtools::document() and the roxygen2 documentation of the function. As you can see I am using a very simple example that should run with no problems... One more thing to say is that when I run devtools::check() all my examples pass, so I don't understand why pkgdown is failing.
Thank you so much for your help.
Best,
Error message
Reading 'man/merge.Rd'
Error : Failed to parse Rd in merge.Rd
i unused argument (output_handler = evaluate::new_output_handler(value = pkgdown_print))
Error: callr subprocess failed: Failed to parse Rd in merge.Rd
i unused argument (output_handler = evaluate::new_output_handler(value = pkgdown_print))
.Rd file
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/merge.R
\name{merge}
\alias{merge}
\title{Merge two tables}
\usage{
merge(x, y)
}
\arguments{
\item{x}{data frame: referred to \emph{left} in R terminology, or \emph{master} in
Stata terminology.}
\item{y}{data frame: referred to \emph{right} in R terminology, or \emph{using} in
Stata terminology.}
}
\value{
a data.table joining x and y.
}
\description{
This is the main and, basically, the only function in joyn.
}
\examples{
x <- c(1, 2)
}
roxygen2 documentation
#' Merge two tables
#'
#' This is the main and, basically, the only function in joyn.
#'
#' #param x data frame: referred to *left* in R terminology, or *master* in
#' Stata terminology.
#' #param y data frame: referred to *right* in R terminology, or *using* in
#' Stata terminology.
#' #return a data.table joining x and y.
#' #export
#' #import data.table
#'
#' #examples
#' x <- c(1, 2)
This error comes from downlit::evaluate_and_highlight (sad it's not reported in the output), and can be fixed by installing the development version of downlit:
library(devtools)
install_github('r-lib/downlit')
It make sense only if you use the git version also from pkgdown, the stable pkgdown (version 1.6.1) runs just fine with the stable downlit. Of course development version of any package can break at any time, but until it doesn't, it's just alright.

R package data not available when importing in another package

I have one package "testing" with a data object "test_data" saved in data folder under file name "test_data.RData".
testing contains one function hello() that uses this data object
#' hello
#'
#' #return Prints hello "your_name"
#' #export
#'
#' #examples
#' hello()
hello <- function(your_name = "") {
print(paste("test_data has", nrow(test_data), "rows"))
print(sprintf("Hello %s!", your_name))
}
the following code works fine:
require(testing)
testing::hello()
[1] "test_data has 32 rows"
[1] "Hello !"
but this fails:
testing::hello()
Error in nrow(test_data) : object 'test_data' not found
Actually I do not use it directly but in another package testingtop that imports this function:
#' Title
#'
#' #export
#' #importFrom testing hello
hello2 <- function(){
hello()
}
I have testing in the Imports section of DESCRIPTION and this fails.
require(testingtop)
testingtop::hello2()
Error in nrow(test_data) : object 'test_data' not found
If I put it in Depends it works if I load the package with library()
otherwise it still fails:
> library(testingtop)
Loading required package: testing
> testingtop::hello2()
[1] "test_data has 32 rows"
[1] "Hello !"
Restarting R session...
> testingtop::hello2()
Error in nrow(test_data) : object 'test_data' not found
if it was a function instead of a data object Imports would be fine, why is it different with a data object and I need to load the imported package? Did I miss something? And is it related to LazyData and LazyLoad ?
Probably a duplicate of this question
SO I think I've found the solution from the doc of the data function ?data
Use of data within a function without an envir argument has the almost always undesirable side-effect of putting an object in the user's workspace (and indeed, of replacing any object of that name already there). It would almost always be better to put the object in the current evaluation environment by data(..., envir = environment()). However, two alternatives are usually preferable, both described in the ‘Writing R Extensions’ manual.
For sets of data, set up a package to use lazy-loading of data.
For objects which are system data, for example lookup tables used in calculations within the function, use a file ‘R/sysdata.rda’ in the package sources or create the objects by R code at package installation time.
A sometimes important distinction is that the second approach places objects in the namespace but the first does not. So if it is important that the function sees mytable as an object from the package, it is system data and the second approach should be used.
Putting the data in the internal data file made my function hello2() see it
> testingtop::hello2()
[1] "test_data has 32 rows"
[1] "Hello !"
To supplement Benoit's answer. I had essentially this problem, but when using my package data as a default for a function parameter. In that case there's a third solution in the ?data help file: "In the unusual case that a package uses a lazy-loaded dataset as a default argument to a function, that needs to be specified by ::, e.g., survival::survexp.us."
This third approach solved it for me. (But I found it thanks to Benoit's link.)

What can cause devtools::document() and devtools::lint() to stop recognizing imports?

I was modifying my R package and suddenly document() stopped recognizing the functions I was getting using #importFrom. The only way I could use my package was to prefix package names (e.g. stringr::str_detect). Since I have a lot of these, this took a very long time. This started happening after I deleted my NAMESPACE file because I accidentally left an #importFrom blank. devtools::document() still appears to work fine for my other projects. I've noticed lint() is also seeing these fake problems.
I keep the package files in version control, but haven't seen any obvious reasons it would stop working. What kind of text error could cause this?
Some examples:
I have the following code block defining a utility function in my package:
#' Check if string ends with y.
#' #param x String.
#' #param y String Scalar.
#' #importFrom stringr str_sub str_length
str_ends_with <- function(x, y) {
stopifnot(length(y) == 1)
leny <- str_length(y)
lenx <- str_length(x)
ifelse(lenx < leny, FALSE,
str_sub(x, start = lenx - leny + 1) == y)
}
Yet, lint() sees
R/util.R:69:11: warning: no visible global function definition for 'str_length'
leny <- str_length(y)
^~~~~~~~~~
R/util.R:70:11: warning: no visible global function definition for 'str_length'
lenx <- str_length(x)
^~~~~~~~~~
Calling roxygen2::roxygenize() successfully created a new NAMESPACE file. Usually devtools::document() can usually do this, but apparently not in my case. However, document() works as expected afterwards.

Function imported from dependency not found, requires library(dependency)

I am trying to create an R package that uses functions from another package (gamlss.tr).
The function I need from the dependency is gamlss.dist::TF (gamlss.dist is loaded alongside gamlss.tr), but it is referenced in my code as simply TF within a call to gamlss.tr::gen.trun.
When I load gamlss.tr manually with library(), this works. However, when I rely on the functions of the dependency automatically being imported by my package through #import, I get an "object not found" error as soon as TF is accessed.
My attempt to be more explicit and reference the function I need as gamlss.dist::TF resulted in a different error ("unexpected '::'").
Any tips on how to use this function in my package would be much appreciated!
The code below reproduces the problem if incorporated into a clean R package (as done in this .zip), built and loaded with document("/path/to/package"):
#' #import gamlss gamlss.tr gamlss.dist
NULL
#' Use GAMLSS
#'
#' Generate a truncated distribution and use it.
#' #export
use_gamlss <- function() {
print("gen.trun():")
gamlss.tr::gen.trun(par=0,family=TF)
#Error in inherits(object, "gamlss.family") : object 'TF' not found
#gamlss.tr::gen.trun(par=0,family=gamlss.dist::TF)
#Error in parse(text = fname) : <text>:1:1: unexpected '::'
y = rTFtr(1000,mu=10,sigma=5, nu=5)
print("trun():")
truncated_dist = gamlss.tr::trun(par=0,family=TF, local=TRUE)
model = gamlss(y~1, family=truncated_dist)
print(model)
}
use_gamlss() will only start working once a user calls library(gamlss.tr).
This is due to bad design of gamlss.tr in particular the trun.x functions (they take character vectors instead of family objects / they evaluate everything in the function environment instead of the calling environment).
To work around this, you have to make sure that gamlss.distr is in the search path of the execution environment of gamlss.tr functions (This is why ## import-ing it in your package does not help: it would need to be #' #import-ed in gamlss.tr).
This can be achieved by adding it to Depends: of your package.
If you want to avoid that attaching your package also attaches gamlss.distr, you could also add the following at the top of use_gamlss:
nsname <-"gamlss.dist"
attname <- paste0("package:", nsname)
if (!(attname %in% search())) {
attachNamespace(nsname)
on.exit(detach(attname, character.only = TRUE))
}
This would temporarily attach gamlss.dist if it is not attached already.
You can read more on namespaces in R in Hadley Wickham's "Advanced R"

Why does using "<<-" in a function in the global workspace work, but not in a package?

I'm creating a package using devtools and roxygen2 (in RStudio), however after I've built the package my function no longer works as intended. Yet, if I load the function's .R file and run the function from there in RStudio, it works perfectly. I've created another package using this method before and it worked fine (13 functions all working as intended from my other package), yet I cant seem to get this new one to work.
To start creating the package I start with:
library("devtools")
devtools::install_github("klutometis/roxygen")
library(roxygen2)
setwd("my parent directory")
create("triale")
All is working fine so far. So I put my .R file containing my function in the R folder under the triale folder. The .R file looks like this:
#' Trial Z Function
#'
#' This function counts the values in the columns
#' #param x is the number
#' #keywords x
#' #export
#' #examples
#' trialz()
trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
wcenter= c(rep("BYSTAR-1",10));
df1 <<- data.frame(w_id, wcenter);
countit <<- data.table(df1);
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
Again if I were to just run the code from the .R file, and test the function it works fine. But to continue, next I enter:
setwd("./triale")
document()
The triale documentation is updated, triale is loaded, and the NAMESPACE and trialz.Rd are both written so that trialz.Rd is under the man folder, and NAMESPACE is under the triale folder as intended. Next I install triale:
setwd("..")
install("triale")
Which I know works because I get the following:
Installing triale
"C:/PROGRA~1/R/R-31~1.3/bin/x64/R" --vanilla CMD INSTALL \
"C:/Users/grice/Documents/R/triale" \
--library="C:/Users/grice/Documents/R/win-library/3.1" --install-tests
* installing *source* package 'triale' ...
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* DONE (triale)
Reloading installed triale
Package is now built, so I do the following:
library("triale")
library("data.table")
Note whenever I load the package data.table I get the following error message:
data.table 1.9.4 For help type: ?data.table
*** NB: by=.EACHI is now explicit. See README to restore previous behaviour.
However it doesnt seem to affect my function. So now its time to test my function from my package:
trialz(25)
This goes through, and I of course get a populated df1, and countit, but for whatever reason view is always empty (as in 0 obs. of 0 variables).
So I test my work using the dummy code below:
>trialy = function(x) {wid= c(25,x,25,25,25,1,1,1,1,1);
wc= c(rep("BYSTAR-1",10));
df2 <<- data.frame(wid, wc);
countitt <<- data.table(df2);
viewer <<- countitt[, .N, by = list(wid, wc)];
View(viewer)}
>trialy(25)
Even though this is the same exact code with just the names changed around it works. Dumbfounded I open trialz.R and copy the function from there and run it as below, and that works:
> trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
wcenter= c(rep("BYSTAR-1",10));
df1 <<- data.frame(w_id, wcenter);
countit <<- data.table(df1);
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
> trialz(25)
Since I've created a package before I know my method is solid (that package had 13 dif. functions, all of which worked). I just don't understand how a function can work fine as written, yet when I package it, the function no longer works.
Again here is where it stops working as intended when using my package:
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
And my end result should look something like this, if my package worked:
wid wc N
1 25 BYSTAR-1 5
2 1 BYSTAR-1 5
Can anyone explain why view is never populated after I package my function? I've tested it as much as I know how, and my results should be reproducible for anyone thats willing to try it for themselves.
Thanks, I appreciate any feedback.
Your problem here is that "<<-" does not create variables in the global environment but rather in the parent environment. (See help("<<-").)
The parent environment of a function is the environment in which it has been defined. In the case where you defined your function directly in your workspace, this parent environment actually is the same as your workspace environment (namely: .GlobalEnv), which is why your variables are assigned values as you expect them to. In the case where your function is packaged, however, the parent environment is the package environment and not the .GlobalEnv! This is why you do not see your variables being assigned values in your workspace.
Refer to the chapter on environments in Hadley's book and How R Searches and Finds Stuff for more details on environments in R.
Note that doing this would not be considered a proper debugging technique, to say the least. In general, you never want to use the "<<-" operator.
For options on debugging R code, see, e.g., this question. I, in particular, like the debugonce function very well. See ?debugonce.
I forgot one important part when editing my description file in that I for got to add
Imports: data.table
Also the NAMESPACE file needed to include the data.table package as an import as well, like so:
import(data.table)
export(Z)
export(AS) .... etc.
Doing this ensures that whenever a function within your package uses a function from another package, that (second) package is called up before your code is executed.

Resources