Use explicit namespace with infix operator - r

The dplyr R package has the %>% operator, which is a custom infix operator. If one attaches the namespace with library(dplyr) one can use this operator. In library code the library(dplyr) at the top of the file has no effect because the environment after executing the source code is stored; loaded packages have no effect on that.
So in order to use this in my library, I have these options:
Just use library(dplyr) at the beginning of each function.
Do not use the infix operator and rather write the functions with out the “pipe” operator %>%.
Try to use dplyr::%>%.
The last option is what I want to do, but I cannot seem to get the syntax right. I have tried
dplyr::%>%
and get parsing errors. Also
dplyr::`%>%`
does not work. And
`dplyr::%>%`
does not work either. I don't think that there is any other way to place the backticks. Is this something that is possible in R or do I just have to use option 1 or 2?

Just import the pipe operator, by adding a line like
importFrom(magrittr, "%>%")
in your NAMESPACE file, or if you're using roxygen2, putting
#' #importFrom magrittr %>%
into one of your .R files to do the same thing.
You may or may not want to export it as well. Do export it with a line like
export("%>%")
in your NAMESPACE file or with roxygen2
#' #export
magrittr::`%>%`
if you want your users to use the pipe operator when they are using your package. Don't export it if you only need it to be available internally.

Related

How can I use something like `package::%to%` in a function/package

I want to use functions from the expss package in my own functions/packages. I usually call the functions along with their packages (e.g. dplyr::mutate(...)).
The expss package has a function/operator %to%, and I don't know how I can do the same here, i.e. expss::%to% doesn't work, neither does expss::'%to%'.
What can I do?
Infix operators must be attached to be usable; you can’t use them prefixed with the package name.1
Inside a package, the conventional way is to add an importFrom directive to your NAMESPACE file or, if you’re using ‘roxygen2’, add the following Roxygen directive somewhere:
#' #importFrom expss %to%
Outside of package code, you could use ‘box’ to attach just the operator:
box::use(expss[`%to%`])
Or you can use simple assignment (this is the easiest solution in the simplest case but it becomes a lot of distracting code for multiple operators):
`%to%` = expss::`%to%`
1 Except using regular function call syntax:
expss::`%to%`(…)

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.

Use `[` method from data.table package in package development

We are creating a package where one of our functions uses functions of the data.table package.
Instead of importing entire packages through our roxygen header, we try to use :: as much as possible in our code.
For a function, this is easy. For example:
data.table::setkey(our_data_1, our_variable)
Yet, we do not know how to do this for a method. For example:
our_data_3 <- our_data_1[our_data_2, roll = "nearest"]
where [ has a specific method for data.tables, which is indicated by:
methods(`[`)
I have tried multiple approaches. Multiple combinations, using #importFrom, failed. For example, adding the following line to our roxygen header...
#importFrom data.table `[.data.table`
...returned the following when running devtools::document():
Warning message:
object ‘[.data.table’ is not exported by 'namespace:data.table'
I have also tried things like [.data.table within our code, but those failed as well...
Importing the entire data.table package in our roxygen header worked (#import data.table), but this is not preferred since we want to refer to the package of each function within our code (or at least use #importFrom).
Is there a way to use the [ method of data.table within the code of a function without importing the entire data.table package? Or is it at least possible to only import the method, for example through using #importFrom in our roxygen header?
Thank you in advance!
There is no need to import S3 methods, they are automatically dispatched by class of an object.
In case of [ data.table method, there is a trick which we use to ensure that data.table passed to a library that expects data.frame, will be handled properly, as a data.frame. This handling is decided based on NAMESPACE file. If you don't import data.table in NAMESPACE then data.table method assumes you want to use it as data.frame.
You can state your intent explicitly by using extra variable .datatable.aware=TRUE in any of you R script files.
You should read Importing data.table vignette where this is well described.
I also put example package which you can run and debug from there if for some reason your code will still not work: https://gitlab.com/jangorecki/useDTmethod
I think you don't need to import S3 method or to use :: like we do on functions.
In my opinion you just need to add data.table as a dependency in DESCRIPTION and it should be working.
R will know that you are applying [ to a data.table object and will use the correct method.

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.

Magrittr functions - how to package them?

I have two related questions about writing functions in magrittr package & including them in a package.
In normal way of writing a function, you can specify library(package.a) within function call if any of the steps uses a function from package.a. How would you call this in pipe environment (from magrittr)?
This part of the question arose when I tried to package my functions, and a few of my functions use magrittr's way of creating functions. I wasn't able to add those functions to package. Devtools package's combine function didn't recognize %>% pipe. Basically I had to re-write them to normal functions to include them in the package. How do you overcome this?
Update your NAMESPACE file, see 1.5 Package namespaces.
Add import(magrittr), don't forget to add Imports: magrittr in DESCRIPTION file.
Regarding your comment on ::.
While you are importing all magrittr exported function by using import(magrittr) you don't have to use :: operator to point the package.
Of course as long as you did not create a function with the same name in your package which would override the name from imported package, then you do need ::.
Also the :: would be needed if you would used importFrom() instead of import() and you did not import required function - that might be not recommended anyway.
Another case where you may want to use :: is when you use Suggests or Enhances, none of them is in scope of that question anyway.

Resources