Difference between environment and namespace - r

I know what a namespace is from other languages but in R I just cannot find a difference between the environment and namespace. Could anyone explain this since in the tutorials I have read (as The Art of R Programming and others) I just cannot find a distinction?

A namespace is something specific to a package. It is defined as a list of directive that allow you to import functions from other packages to be used locally or to export your functions and classes to be used in R.
So if you have created in your package a function called foo you will add to your namespace something like export(foo) to make your function usable.
If you want to import function from a specific package to use them in yours, you will add import(thePackage)
The environment is simply the space where you associate names to values. You can see it as a context in which you can evaluate functions and expressions.

Related

R: how to properly include libraries in my package

I'm writing by first R-Package and was wondering what the right way is to include other libraries, like ggplot2.
So there are two places where an import statement can go in my package. The DESCRIPTION file and the NAMESPACE, where the latter requires to include ggplot in some roxagen statement like #'#import ggplot2.
Actually I thought that is is enough to include ggplot2 inside DESCRIPTION, as I thought that loading my packages will also load or dependencies, however, when ggplot2 is not in the namespace it seems like I cannot use function, e.g. aes, ggplot without writing ggplot2::aes or ggplot2::gpplot. So for what are the import statements in each of the config files, i.e. DESCRIPTION and NAMESPACE?
The one required step is to include ggplot2 under Imports: in your DESCRIPTION file. This ensures that ggplot2 is installed when your package is installed.
Then, to use functions from ggplot2 in your package, you need to tell R where to look for them. You can do this in 3 ways:
Put the name of the package before the function name when you use it: ggplot2::aes(). This is my preferred method, as it doesn’t add anything extra to your NAMESPACE, avoids any name collisions, and avoids breakage if you later rework or remove a function.
Import specific functions as you use them. Do this by putting #’ #importFrom ggplot2 aes in the roxygen block above the function using it. Add however many function names you need to that line. After doing that, you can use aes() directly without having to specify the namespace it’s coming from with ggplot2::aes(). This can be convenient if you’re working with a lot of functions (like with ggplot2), but I recommend using the first option instead in general to keep your NAMESPACE tidier. You technically only need to include the #importFrom line for once in your package for any function, but I recommend including it for each function that is using the imported functions. That way, if you ever rework or remove a function, the other functions don’t break.
You can import a whole package of functions by putting #’ #import ggplot2 in a roxygen block. This imports every function from a package. This can be a lot for big packages like ggplot2 and dplyr, and the can potentially cause issues, so I suggest never doing this and instead importing only the specific functions you need or calling them with ggplot2::aes().
If you depend on a package you should put it in the Imports field of the DESCRIPTION file, after which you can use pkgname::function() in your code.
usethis::use_package() function can help you do this.
If you want your code to be able to use any code of the package without the use of ::, you should put a roxygen comment somewhere like this:
#' #import pkgname
NULL
This then gets ported by roxygen2 to your NAMESPACE file.
If you want to specifically use some functions (but not others), you can use the following that is used by roxygen2:
#' #importFrom pkgname fun1 fun2
NULL
The usethis::use_import_from() function can help you do the above. In the examples above NULL only indicates that you're not documentating a function or data, and you can use it at the end of a documentation comment block.

R with roxygen2: How to use a single function from another package?

I'm creating an R package that will use a single function from plyr. According to this roxygen2 vignette:
If you are using just a few functions from another package, the
recommended option is to note the package name in the Imports: field
of the DESCRIPTION file and call the function(s) explicitly using ::,
e.g., pkg::fun().
That sounds good. I'm using plyr::ldply() - the full call with :: - so I list plyr in Imports: in my DESCRIPTION file. However, when I use devtools::check() I get this:
* checking dependencies in R code ... NOTE
All declared Imports should be used:
‘plyr’
All declared Imports should be used.
Why do I get this note?
I am able to avoid the note by adding #importFrom dplyr ldply in the file that is using plyr, but then I end but having ldply in my package namespace. Which I do not want, and should not need as I am using plyr::ldply() the single time I use the function.
Any pointers would be appreciated!
(This question might be relevant.)
If ldply() is important for your package's functionality, then you do want it in your package namespace. That is the point of namespace imports. Functions that you need, should be in the package namespace because this is where R will look first for the definition of functions, before then traversing the base namespace and the attached packages. It means that no matter what other packages are loaded or unloaded, attached or unattached, your package will always have access to that function. In such cases, use:
#importFrom plyr ldply
And you can just refer to ldply() without the plyr:: prefix just as if it were another function in your package.
If ldply() is not so important - perhaps it is called only once in a not commonly used function - then, Writing R Extensions 1.5.1 gives the following advice:
If a package only needs a few objects from another package it can use a fully qualified variable reference in the code instead of a formal import. A fully qualified reference to the function f in package foo is of the form foo::f. This is slightly less efficient than a formal import and also loses the advantage of recording all dependencies in the NAMESPACE file (but they still need to be recorded in the DESCRIPTION file). Evaluating foo::f will cause package foo to be loaded, but not attached, if it was not loaded already—this can be an advantage in delaying the loading of a rarely used package.
(I think this advice is actually a little outdated because it is implying more separation between DESCRIPTION and NAMESPACE than currently exists.) It implies you should use #import plyr and refer to the function as plyr::ldply(). But in reality, it's actually suggesting something like putting plyr in the Suggests field of DESCRIPTION, which isn't exactly accommodated by roxygen2 markup nor exactly compliant with R CMD check.
In sum, the official line is that Hadley's advice (which you are quoting) is only preferred for rarely used functions from rarely used packages (and/or packages that take a considerable amount of time to load). Otherwise, just do #importFrom like WRE advises:
Using importFrom selectively rather than import is good practice and recommended notably when importing from packages with more than a dozen exports.

Code to export a function in R

Is it possible to export a function in R by evaluating an expression? What I would like to write something like
my.great.fun = function(x) x
export(my.great.fun)
in a R file in a package and have my.great.fun exported.
Then you can evaluate that in a loop, conditionally, define family of functions concisely etc. The immediate application would be generating and exporting setters and getters for an S4 class in two lines of code as opposed to as many lines as there are slots. I saw the package R.MethodsS3, but the export option doesn't seem to do anything other than setting an attribute, ditto the now un-exported export function therein. setGeneric for S4 doesn't have a similar option. I am a fairly navigated R developer with several packages under my belt, so it doesn't help to point me to standard documentation about the NAMESPACE file. roxygen #export is not a solution because it doesn't work in loops, is not in the language, is not first, second or even third class in R. It seems to me we can create functions, generics of S3 and S4 flavors, methods of S3 and S4 flavors all in the language, and the only bit that is missing is the export part: omission or hole in my knowledge? Thanks
You can add the function to an environment when calling export. Then in .onLoad you attach the environment. For instance, see rex_mode in package rex. Reading packages written by the R intelligentsia pays off.

How to use S3 methods from another package which uses export rather than S3method in its namespace without using Depends or library()

I'm working on an R package at present and trying to follow the best practice guidelines provided by Hadley Wickham at http://r-pkgs.had.co.nz. As part of this, I'm aiming to have all of the package dependencies within the Imports section of the DESCRIPTION file rather than the Depends since I agree with the philosophy of not unnecessarily altering the global environment (something that many CRAN and Bioconductor packages don't seem to follow).
I want to use functions within the Bioconductor package rhdf5 within one of my package functions, in particular h5write(). The issue I've now run into is that it doesn't have its S3 methods declared as such in its NAMESPACE. They are declared using (e.g.)
export(h5write.default)
export(h5writeDataset.matrix)
rather than
S3method(h5write, default)
S3method(h5writeDataset, matrix)
The generic h5write is defined as:
h5write <- function(obj, file, name, ...) {
res <- UseMethod("h5write")
invisible(res)
}
In practice, this means that calls to rhdf5::h5write fail because there is no appropriate h5write method registered.
As far as I can see, there are three solutions to this:
Use Depends rather than Imports in the DESCRIPTION file.
Use library("rhdf5") or require("rhdf5") in the code for the relevant function.
Amend the NAMESPACE file for rhdf5 to use S3methods() rather than export().
All of these have disadvantages. Option 1 means that the package is loaded and attached to the global environment even if the relevant function in my package is never called. Option 2 means use of library in a package, which while again attaches the package to the global environment, and is also deprecated per Hadley Wickham's guidelines. Option 3 would mean relying on the other package author to update their package on Bioconductor and also means that the S3 methods are no longer exported which could in turn break other packages which rely on calling them explicitly.
Have I missed another alternative? I've looked elsewhere on StackOverflow and found the following somewhat relevant questions Importing S3 method from another package and
How to export S3 method so it is available in namespace? but nothing that directly addresses my issue. Of note, the key difference from the first of these two is that the generic and the method are both in the same package, but the issue is the use of export rather than S3method.
Sample code to reproduce the error (without needing to create a package):
loadNamespace("rhdf5")
rdhf5::h5write(1:4, "test.h5", "test")
Error in UseMethod("h5write") :
no applicable method for 'h5write' applied to an object of class
"c('integer', 'numeric')
Alternatively, there is a skeleton package at https://github.com/NikNakk/s3issuedemo which provides a single function demonstrateIssue() which reproduces the error message. It can be installed using devtools::install_github("NikNakk/s3issuedemo").
The key here is to import the specific methods in addition to the generic you want to use. Here is how you can get it to work for the default method.
Note: this assumes that the test.h5 file already exists.
#' #importFrom rhdf5 h5write.default
#' #importFrom rhdf5 h5write
#' #export
myFun <- function(){
h5write(1:4, "test.h5", "test")
}
I also have put up my own small package demonstrating this here.

Importing / Exporting packages using NAMESPACE

I am currently developing a plug-in for the R-Commander GUI. In this package I am using a great deal of other packages which I simply attached by using the Depends option in the description file.
I am however now switching them over to the Imports option and am experiencing some problems with it.
Because I want to use some functions not only internally in my own code, but also be able to print and use them in the script window of R Commander, I will also have to export them in the namespace.
Let's take for example the biclust package. This package has the following exports in its namespace:
# First a bunch of functions are exported (Note that the biclust function is not in here!)
export(drawHeatmap,drawHeatmap2,bubbleplot,...,heatmapBC)
# The classes are exported
exportClasses(BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
# Methods are exported
exportMethods(biclust,show,summary)
So when I library(biclust) in an R session, it works as intended, meaning I can use the biclust method/function in the R console.
Now this how my namespace file looks like (or at least the part of it relevant to this discussion)
# I select those functions I need and import them.
importFrom(biclust, drawHeatmap,...,biclustbarchart)
# I import all the classes
importClassesFrom(biclust,BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
# I import all the methods
importMethodsFrom(biclust,show,summary,biclust)
# I now export all of the previous again so I can use the doItAndPrint functionality in R Commander
export( drawHeatmap,...,biclustbarchart)
exportClasses(BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
exportMethods(biclust,show,summary)
However when I load in my own package now, it is not working as intended. While functions such as drawHeatmap are working, the biclust method/function can not be found.(Though I have clearly imported and exported the method.)
Seemingly the only way to get this working, is to put the biclust method also in the normal export() command.
export(biclust,drawHeatmap,...,biclustbarchart)
Could someone clarify what I am doing wrong or what is going on here? Why are the same exports working for the biclust package, but not for my own package?
The only description of your error is that "it is not working as intended", so the following is a little stab in the dark.
It's useful to distinguish between methods and the generics that they are associated with. Biclust makes available both, and they are tightly associated. importFrom(biclust, biclust) imports the generic and associated methods, importMethodsFrom(biclust, biclust) imports the biclust methods defined in the biclust package, and implicitly the generic(s) on which the methods are defined. These are functionally equivalent so far; I think the original intention of importMethodsFrom() was when pkgA defines a generic, pkgB defines methods on the generic, and pkgD wants to use the generic from pkgA and the methods on that generic defined in pkgA and pkgB -- import(pkgA, foo), importMethodsFrom(pkgB, foo).
On the other end, when you say exportMethods(foo), it instructs R to make foo methods defined in your package available for others to use. But there are no foo methods defined in your package, so nothing is exported (maybe this should generate an error, or the methods that you import should be exported again). On the other hand, export(foo) tells R to export the foo generic, which is available for export -- it's the symbol that you'd imported earlier. (You mention that you "put the biclust method also in the normal export()", but actually it is the generic (and any methods associated with it) available for export.) So exporting biclust, rather than methods defined on it, seems to be what you want to do.
Normally, I would say that importing and then re-exporting functions or generics defined in other packages is not the right thing to do -- biclust, not your package, provides and documents the generic, and biclust would probably belong in Depends: -- presumably, many other functions from biclust are typically used in conjunction with the generic. Perhaps your Rcommander GUI is an exception.
Even though Imports: implies additional work (in the NAMESPACE file), it is usually the case that packages belong as Imports: rather than Depends: -- it makes the code in your package much more robust (imported functions are found in the package name space, rather than on the search path that the user can easily modify) and reduces the likelihood that the user experiences name clashes between identical symbols defined in different packages.

Resources