I'm developing an R package, pk, say. I've successfully installed it and used it, and now I'm trying to clean up the examples with the help of the run_examples function in the devtools package. However, it crashes on the very first example:
> require(pk)
> require(devtools)
> run_examples("~/[full path]/pk")
Updating pk documentation
Running 45 example files in pk
--------------------------------------------------------------------------------
Loading pk
Running examples in pk-package.Rd
--------------------------------------------------------------------------------
1> ########################################################################
1> ## Simulate a dataset ... blah blah
1> set.seed(1)
1> x = my_pk_fun(a = 1)
Error in eval(expr, envir, enclos) : could not find function "my_pk_fun"
Loading pk
As I already loaded my package (using require), what more do I have to do to make my_pk_fun visible to run_examples? I've checked that my_pk_fun is indeed present in my R session.
UPDATE:
Following the comment by Dirk, I examined my namespace file, and found it to be completely empty. As suggested (though not recommended) by the documentation, I inserted exportPattern("^[^\\.]"), which, it seems, is supposed to export all of the functions, including my_pk_fun. However, upon repeating the experiment above, (a) I get the same error, and (b) the contents of the namespace file are deleted! Why does run_examples empty my namespace file?
I conjecture a resolution of my own question:
One detail that I omitted is that before I could get run_examples to do anything at all, it required me to first install the roxygen2 package (even though roxygen2 is listed only under "suggests" in the devtools documentation!).
When digging through the source code of run_examples, I did indeed find some use of roxygenize. It has been previously noted that roxygenizing a package can have the effect of rewriting the NAMESPACE file.
To be explicit, the reason that run_examples empties my NAMESPACE file is that (1) run_examples roxygenized my package while (2) I never included any # #export command (or any other roxygen2-speak, for that matter) in my source files.
Conclusion: Unless you are building your package within the roxygen2 framework, and including all of your .Rd documentation as comments in your source code, then do not use run_examples! It seems like there should be a warning about this in the run_examples documentation.
A way out: If you really must use run_examples, and you're willing to learn a little bit about roxygen, which is actually pretty cool, then start here.
Related
I’ve written some R functions and dropped them into a script file using RStudio. These are bits of code that I use over and over, so I’m wondering how I might most easily create an R package out of them (for my own private use).
I’ve read various “how to” guides online but they’re quite complicated. Can anyone suggest an “idiot’s guide” to doing this please?
I've been involved in creating R packages recently, so I can help you with that. Before proceeding to the steps to be followed, there are some pre-requisites, which include:
RStudio
devtools package (for most of the functions involved in creation of a package)
roxygen2 package (for roxygen documentation)
In case you don't have the aforementioned packages, you can install them with these commands respectively:
install.packages("devtools")
install.packages("roxygen2")
Steps:
(1) Import devtools in RStudio by using library(devtools).
(devtools is a core package that makes creating R packages easier with its tools)
(2) Create your package by using:
create_package("~/directory/package_name") for a custom directory.
or
create_package("package_name") if you want your package to be created in current workspace directory.
(3) Soon after you execute this function, it will open a new RStudio session. You will observe that in the old session some lines will be auto-generated which basically tells R to create a new package with required components in the specified directory.
After this, we are done with this old instance of RStudio. We will continue our work on the new RStudio session window.
By far the package creation part is already over (yes, that simple) however, a package isn't directly functionable just by its creation plus the fact that you need to include a function in it requires some additional aspects of a package such as its documentation (where the function's title, parameters, return types, examples etc as mentioned using #param, #return etc - you would be familiar if you see roxygen documentation like in some github repositories) and R CMD checks to get it working.
I'll get to that in the subsequent steps, but just in case you want to verify that your package is created, you can look at:
The top right corner of the new RStudio session, where you can see the package name that you created.
The console, where you will see that R created a new directory/folder in the path that we specified in create_package() function.
The files panel of RStudio session, where you'll notice a bunch of new files and directories within your directory.
(4) As you mentioned in your words, you drop your functions in a script file - hence you will need to create the script first, which can be done using:
use_r("function_name")
A new R script will pop up in your working session, ready to be used.
Now go ahead and write your function(s) in it.
(5) After your done, you need to load the function(s) you have written for your package. This is accomplished by using the devtools::load_all() function.
When you execute load_all() in the console, you'll get to know that the functions have been loaded into your package when you'll see Loading package_name displayed in console.
You can try calling your functions after that in the console to verify that they work as a part of the package.
(6) Now that your function has been written and loaded into your package, it is time to move onto checks. It is a good practice to check the whole package as we make changes to our package. The function devtools::check() offers an easy way to do this.
Try executing check() in the console, it will go through a number of procedures checking your package for warnings/errors and give details for the same as messages on the screen (pertaining to what are the errors/warnings/notes). The R CMD check results at the end will contain the vital logs for you to see what are the errors and warnings you got along with their frequency.
If the functions in your package are written well, (with additional package dependencies taken care of) it will give you two warnings upon execution of check:
The first warning will be regarding the license that your package uses, which is not specified for a new pacakge.
The second should be the one for documentation, warning us that our code is not documented.
To resolve the first issue which is the license, use the use_mit_license("license_holder_name") command (or any other license which suits your package - but then for private use as you mentioned, it doesn't really matter what you specify if only your going to use it or not its to be distributed) with your name as in place of license_holder_name or anything which suits a license name.
This will add the license field in the .DESCRIPTION file (in your files panel) plus create additional files adding the license information.
Also you'll need to edit the .DESCRIPTION file, which have self-explanatory fields to fill-in or edit. Here is an example of how you can have it:
Package: Your_package_name
Title: Give a brief title
Version: 1.0.0.0
Authors#R:
person(given = "Your_first_name",
family = "Your_surname/family_name",
role = c("package_creator", "author"),
email = "youremailaddress#gmail.com",
comment = c(ORCID = "YOUR-ORCID-ID"))
Description: Give a brief description considering your package functionality.
License: will be updated with whatever license you provide, the above step will take care of this line.
Encoding: UTF-8
LazyData: true
To resolve the documentation warning, you'll need to document your function using roxygen documentation. An example:
#' #param a parameter one
#' #param b parameter two
#' #return sum of a and b
#' #export
#'
#' #examples
#' yourfunction(1,2)
yourfunction <- function(a,b)
{
sum <- a+b
return(sum)
}
Follow the roxygen syntax and add attributes as you desire, some may be optional such as #title for specifying title, while others such as #import are required (must) if your importing from other packages other than base R.
After your done documenting your function(s) using the Roxygen skeleton, we can tell our package that we have documented our functions by running devtools::document(). After you execute the document() command, perform check() again to see if you get any warnings. If you don't, then that means you're good to go. (you won't if you follow the steps)
Lastly, you'll need to install the package, for it to be accessible by R. Simply use the install() command (yes the same one you used at the beginning, except you don't need to specify the package here like install("package") since you are currently working in an instance where the package is loaded and is ready to be deployed/installed) and you'll see after a few lines of installation a statement like "Done (package_name)", which indicates the installation of our package is complete.
Now you can try your function by first importing your package using library("package_name") and then calling your desired function from the package. Thats it, congrats you did it!
I've tried to include the procedure in a lucid way (the way I create my R packages), but if you have any doubts feel free to ask.
I am building R package. Recently, I deleted and renamed several functions in R/allFunctions.R. I had previously been able to automatically update NAMESPACE, but for some reason, I am not able to now, and get some errors as follows:
library(packageName)
library(roxygen2)
library(devtools)
install()
ERROR: loading failed
* removing ‘/Library/Frameworks/R.framework/Versions/3.1/Resources/library/packageName’
* restoring previous ‘/Library/Frameworks/R.framework/Versions/3.1/Resources/library/packageName’
Error: Command failed (1)
document()
Updating packageName documentation
Loading packageName
Warning message:
In setup_ns_exports(pkg, export_all) :
Objects listed as exports, but not present in namespace: functionOne, functionTwo
I see that clearly I have some objects that are not present in namespace that are listed as exports. However, I removed all #export in the allFunctions.R file. I see in NAMESPACE that some newly named function names are not there, and that some old (since renamed) function names are still there. I could change it by hand, but I know that is dangerous, and want to avoid those poor techniques.
If you have any ideas, please let me know! Thank you.
#jtr13's Answer worked for me as well. Just run devtools::document() a second time and the warning goes away.
> devtools::document()
Updating pavm documentation
Loading pavm
Writing NAMESPACE
Deleting evlCalcTime.Rd
Deleting initTimeStamp.Rd
Warning message:
In setup_ns_exports(pkg, export_all) :
Objects listed as exports, but not present in namespace: evlCalcTime,
initTimeStamp
> devtools::document()
Updating pavm documentation
Loading pavm
I just did a similar thing: I deleted 3 exported functions from R/allFunctions.R and ran devtools::document(). This gave me the following error:
Warning message:
In setup_ns_exports(pkg, export_all) :
Objects listed as exports, but not present in namespace: getAccounts, getClients, getDeposits
I solved the problem by manually deleting the 3 export() functions from the NAMESPACE file.
In my experience, this is often a typo-mismatch between function definition and roxygen statement, especially when camelCase notation is involved, for example:
#' #export functionOne
functionone <- function() { ... }
I am maintaining an R package that recently started throwing the following warning during R CMD check packagename:
** testing if installed package can be loaded
Warning: multiple methods tables found for ‘append’
(The package is called phyloseq, and the branch that is currently causing me this problem is here)
Refined subquestions:
So the "multiple methods tables" part, this seems to imply that I have two dependent packages with a collision over dispatch for the append method. Right?
I don't have a function/method named "append" in this package, and don't import any.
I was able to reproduce the warning message in a new R session by simply loading two of the packages in R at the same time, one of which (RJSONIO) is a second-level dependency -- by which I mean one of my dependencies (biom) depends on it, but not mine:
library("RJSONIO");library("Biostrings")
Which throws the warning in the R session:
multiple methods tables found for ‘append’
And naturally, append is exported in the NAMESPACE file of both RJSONIO and Biostrings. What I don't understand is why this should cause a problem when loading my package. The packages I directly depend on (Biostrings-2.28.0, biom-0.3.8) are not fully imported -- certainly not importing any append methods. How else could this conflict arise?
Workaround:
If I update Biostrings to the "devel" version, 2.29.2, then the warning appears to go away. Most users will not do this, however, and I'd still like to understand how this collision is even possible, given the way I specifically imported functions and classes from these packages rather than full Import or Depends.
I'm trying to use Imports: instead of Depends: in the DESCRIPTION files of my packages, yet I still feel I've got some more to understand on this ;-)
What I learned from this post (by the way: awesome post!!!) is that everything my package, say mypkg, imports (say imported.pkg) via Imports: lives in environment imports:mypkg instead of being attached to the search path. When trying to find foo that ships with imported.pkg, R looks in imports:mypkg before traversing the search list. So far, so good.
Actual question
If imported.pkg (imported by mypkg) depends on a certain other package (stated in Depends: section of the package's DESCRIPTION file), do I need to make this very package a Depends: dependency of my package in order for R to find functions of that package? So it seems to me at the moment as otherwise R complains.
Evidence
Seems like simply importing such a package is not enough. As an example, take package roxygen2 (CRAN). It depends on digest while importing a bunch of other packages. I imported it (along with digest as mypkg also needs it) and checked environment imports:mypkg which does list the digest function: "digest" %in% parent.env(asNamespace("mypkg")) returns TRUE
Yet when running roxygenize() from within a function that is part of mypkg, R complains that it can't find digest.
You could have a look at my blog : http://r2d2.quartzbio.com/posts/package-depends-dirty-hack-solution.html
Now i have a better and cleaner solution but not published yet.
Hope it helps.
One of my R package's dependencies displays startup messages when loaded. I would like to suppress these startup messages.
The only fix I found so far was removing the offending package from the Depends: line in my DESCRIPTION file. Then calling suppressPackageStartupMessages(require("offendingPackage")) in .onLoad of my package.
I would rather keep the offending package as part of my Depends, but it seems that anything specified in depends is automatically loaded and therefore can't be supressed.
The suppressPackageStartupMessages() function works if and only if the startup messages are actually written with packageStartupMessage() -- see the help page.
Many packages just use cat(), which one could consider a buglet. In that case
suppressMessages(library(foo))
works better.
If you work with namespaces, you can specify the package in Imports, and load the necessary functions using import or importFrom. This way, the package is not attached, but the necessary functions can be loaded and used by your package. Without attaching, the startup messages are not given, so this approach assures you won't see any startup messages of packages specified in Imports.
Make sure you check that you imported everything that is of importance. If the package you import is dependent on other packages, I'm not sure everything you need to use those functions is imported. You might have to do a bit of puzzling to get everything you need loaded. On the plus side, using Imports assures that any dependencies check will be carried out correctly.
Another option is to not specify the package in Depends, but in Suggests in the DESCRIPTION file, and use the option #Dirk gave you. This will give a correct dependency check if 'dependencies=TRUE' is set in install.packages(). But personally I think using the namespaces is a lot more clean.
A quick hack to do this inline in a script or environment is to override library()/require() to wrap the suppressPackageStartupMessages() method:
> library(here) # This shows a message
here() starts at /home/z/development/
> require(here) # This shows a message
Loading required package: here
here() starts at /home/y
The workaround:
> flibrary <- library
> library <- function(...) suppressPackageStartupMessages(flibrary(...))
> library(here) # No messages
>
> frequire <- require
> require <- function(...) suppressPackageStartupMessages(frequire(...))
> require(here) # No messages
>