27

I'm a maintainer of a CRAN package and get the following messages when loading:

* checking whether package ‘qdap’ can be installed ... [10s/10s] WARNING
Found the following significant warnings:
  Warning: replacing previous import ‘annotate’ when loading ‘NLP’
  Warning: replacing previous import ‘rescale’ when loading ‘scales’

Because I use the plotrix and scales packages as well as the NLP and ggplot packages. They have the functions rescale and annotate in common. This results in a significant warning with the latest CRAN check. So I decide to "fix" it.

I made the description something like this:

Package: qdap
Type: Package
Title: Bridging the gap between qualitative data and quantitative analysis
Version: 1.0.0
Date: 2013-06-26
Author: Tyler Rinker
Maintainer: Tyler Rinker <tyler.rinker@gmail.com>
Depends:
    R (>= 3.0.0),
    ggplot2 (>= 0.9.3.1),
    gdata,
    grid,
Imports:
    NLP,
    openNLP,
    plotrix,
    scales,
LazyData: TRUE
Description: Stuff
License: GPL-2

And added this to some .R files:

#' @import ggplot2 gridExtra RColorBrewer
#' @importFrom scales alpha

But this results in another warning:

* installing *source* package 'qdap' ...
** R
** data
*** moving datasets to lazyload DB
** inst
** preparing package for lazy loading
Warning: replacing previous import 'rescale' when loading 'scales'
Warning: replacing previous import 'annotate' when loading 'NLP'
Warning: replacing previous import 'alpha' when loading 'scales'

How do I use roxygen2's importFrom tag correctly?

I have read: https://github.com/hadley/devtools/wiki/Namespaces

But I learn best from an example where someone had to do this. I'm unsure of how to format the DESCRIPTION file correctly as well as the use of roxygen2 tags to avoid:

* checking whether package ‘qdap’ can be installed ... [10s/10s] WARNING
Found the following significant warnings:
  Warning: replacing previous import ‘annotate’ when loading ‘NLP’
  Warning: replacing previous import ‘rescale’ when loading ‘scales’

Here is the qdap GitHub Repo

Thomas
  • 43,637
  • 12
  • 109
  • 140
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
  • Note that you're still importing both packages though. There isn't a function specific way to import packages. Just look at your NAMESPACE file - you still have imports for all of the packages. – Dason Aug 20 '13 at 19:27
  • Never import an entire package's NAMESPACE. Import all the symbols you need and no more. `@import` is evil. These "replacing previous import warnings" multiply as you start importing NAMESPACES that import other NAMESPACES. – GSee Aug 20 '13 at 19:40
  • @GSee does this mean I have to go through and remove all `@import` and replace with: `@importFrom`? If only people named their functions in elvish and other obscure languages. – Tyler Rinker Aug 20 '13 at 19:43
  • 3
    @TylerRinker: welcome to the "Hates GSee" club. ;-) – Joshua Ulrich Aug 20 '13 at 19:54
  • You could switch to using Depends for everything so that you could at least suppress the "object is masked" messages, but using Depends has its [own problems](http://stackoverflow.com/a/8638902/967840) as I'm sure you know (and is not recommended except for the methods package) Here's a 4 hour old [post from BDR](https://stat.ethz.ch/pipermail/r-help/2013-August/358754.html) – GSee Aug 20 '13 at 20:12
  • I would like to keep `ggplot2` in depends but he conflicts with `NLP`. Is there a way to keep `ggplot2` in depends and not have it squawk? – Tyler Rinker Aug 20 '13 at 20:59
  • 4
    FYI roxygen3 has `@autoImports` which mostly automatically figures out which functions to import. – hadley Aug 21 '13 at 03:43
  • Another reason for hatred: never use Depends... – Karl Forner Aug 21 '13 at 08:11
  • @GSee can you add that as an answer. It's not what I wanted but was the solution. – Tyler Rinker Aug 23 '13 at 02:14
  • 1
    @TylerRinker, but that would draw attention to the question and give people more opportunity to state their hatred for me. ;) – GSee Aug 23 '13 at 13:01
  • 1
    @hadley is roxygen3 and `@autoImports` no longer in the pipeline? I see on the repo "Roxygen development activity has shifted to roxygen2." – C8H10N4O2 Mar 03 '16 at 22:31

3 Answers3

25

The thing to keep in mind is that you cannot have more than one function with the same name in your package's namespace.

Suppose there are two packages, pkgA and pkgB, that both export a function called foo. If you create a package, pkgC, that has import(pkgA) and import(pkgB) in the NAMESPACE. Now, when you call library(pkgC) you'll get a warning:

replacing previous import 'foo' when loading 'pkgB'. 

Now, suppose someone creates another package, pkgD, that has this in the NAMESPACE file:

import(pkgA)
import(pkgB)
import(pkgC)

Then, library(pkgD) will give 2 warnings:

1: replacing previous import ‘foo’ when loading ‘pkgB’ 
2: replacing previous import ‘foo’ when loading ‘pkgB’ 

If everyone adopts the practice of importing entire namespaces, then 30 years from now, there will be a lot of these warnings.

Instead, since you can only have a single "foo" in your package, you should explicitly import the "foo" (and other functions) that you want your package to use. In the above example, the NAMESPACE for pkgD should be

importFrom(pkgB,foo)

If you actually need to use the two functions with the same name from two different packages, one hack you can perform is to import other functions from each package to ensure the packages are installed and their namespaces are loaded, but then refer to the functions you need using :: notation by placing this in your NAMESPACE:

importFrom(pkgA,foo)
importFrom(pkgB,bar)

and then calling functions pkgA::abc() and pkgB::abc() in your code.

Thomas
  • 43,637
  • 12
  • 109
  • 140
GSee
  • 48,880
  • 13
  • 125
  • 145
  • 1
    If you imported two packages that each had a function `foo` into your package, couldn't you use the `::` syntax to distinguish between the two? For example `pkgA::foo()` and `pkgB::foo()`? (Using `importFrom` should dramatically reduce the chances of having to do this) – geneorama Jul 08 '15 at 16:55
  • 2
    @geneorama You can use `pkgA::foo()` to access `foo` from `pkgA`, but it will NOT import it into your package's namespace. Your package's namespace cannot have more than one function with the same name. – GSee Jul 08 '15 at 16:59
  • 1
    I use both `gWidgets::gtable` and `gtable::gtable` in my package, which give me a WARNING. Any suggestions on how to solve this? – Oskar Hansson Aug 29 '15 at 15:52
4

Most likely no longer of use to you but maybe to others: the answer to your question can be found in the website you mention, in particular, here (quoting from source): "No matter how many times you use @importFrom foo bar".

So the correct use of roxygen2's tag @importFrom is: @importFrom package_name function_name. No commas, parenthesis, nothing, just the two names separated by a space (possibly applicable to more than 1 function, in the obvious way).

I have tried this myself just now when generating the documentation for the new version of one of my packages, so it should work.

I hope it helps.

Waldir Leoncio
  • 10,853
  • 19
  • 77
  • 107
Albert Dorador
  • 331
  • 2
  • 9
2

Recently I've found a new way to tackle this problem. I want to import dplyr as well as data.table in development which gives these warnings. To remove the overlap functions, I used importFrom to import every function in data.table except for the overlaps.

ls("package:data.table") %>% 
  setdiff(c("last","first","between",":=")) %>% 
  str_c(collapse = " ")

## "%between% %chin% %flike% %ilike% %inrange% %like% address alloc.col as.data.table as.Date.IDate as.IDate as.ITime as.xts.data.table chgroup chmatch chorder CJ copy cube data.table dcast dcast.data.table fcoalesce fifelse fintersect foverlaps frank frankv fread frollapply frollmean frollsum fsetdiff fsetequal fsort funion fwrite getDTthreads getNumericRounding groupingsets haskey hour IDateTime indices inrange is.data.table isoweek key key<- key2 like mday melt melt.data.table merge.data.table minute month nafill quarter rbindlist rleid rleidv rollup rowid rowidv second set set2key set2keyv setalloccol setattr setcolorder setDF setDT setDTthreads setindex setindexv setkey setkeyv setnafill setnames setNumericRounding setorder setorderv shift shouldPrint SJ tables test.data.table timetaken transpose truelength tstrsplit uniqueN update.dev.pkg wday week yday year"

the setdiff have included all the conflicted function names. Last I importFrom data.table only the functions above.

Hope
  • 109
  • 5