5

I am using neuralnet to train neural networks. The package, more specifically the plotting function of neuralnet, depends on grid, which is a base package since last year. However, unless I load grid manually, the plotting fails:

AND <- c(rep(0,7),1)
OR <- c(0,rep(1,7))
binary.data <- data.frame(expand.grid(c(0,1), c(0,1), c(0,1)), AND, OR)
net <- neuralnet::neuralnet(AND + OR ~ Var1 + Var2 + Var3, binary.data, 
                       hidden = 0, linear.output=FALSE)

if(requireNamespace("grid")) {
  neuralnet::plot.nn(net)
}

> Error in plot.nn(net, rep = i, x.entry, x.out, radius, arrow.length, intercept,  : 
> could not find function "grid.newpage"

Using library(grid) helps, but I want to avoid that because I want to use it in my own package later. R Packages suggests using requireNamespace, but that doesn't help either, as we can see above.

Adding grid:: in front of all calls to grid functions and building the package from source solves the issue, but I'm wondering: is that intended behavior? Looking at the sources of neuralnet, I find no mention of requireNamespace, library or similar. But then why doesn't my requireNamespace take care of loading the package?

sebastianmm
  • 1,148
  • 1
  • 8
  • 26

1 Answers1

4

The problem is that neuralnet only depends on the grid package, when it should instead (or at least also) import it. (See here for one discussion of the difference between the two.)

As a result, when a function in neuralnet calls grid.newpage(), it will only be able to find that function if grid is attached to the search path. But a fully qualified call to neuralnet::neuralnet() does not attach neuralnet, which would trigger attachment of grid; and without grid on the search path, it has no idea what grid.newpage is.

To import grid into neuralnet, add this line to the source package's NAMESPACE file

import(grid)

and this line to its DESCRIPTION file

Imports: grid

and then recompile it.

Community
  • 1
  • 1
Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
  • Thanks. Now, when I publish my package people will use the `neuralnet` package from CRAN, not my compiled version. Could I bypass the issue from my code, e.g. using `attachNamespace`? – sebastianmm Jul 06 '16 at 16:47
  • 1
    @sebastianmm As mentioned in my other answer, linked above (and in the answer to which *it* points) by far the best thing to do is to contact the package maintainers and ask them to have their package import **grid**. You can even supply them with the lines they need to add, and let them know that you've tested it and that it works. Other than that, I think you're stuck with having to Depend on **neuralnet** so that it'll load **grid** when it's attached, which is unfortunate. – Josh O'Brien Jul 06 '16 at 16:54
  • So I just need to move neuralnet from `Imports` to `Depends`? I will contact the maintainer, anyway. Thanks again. – sebastianmm Jul 06 '16 at 16:57
  • You need to do both things mentioned in my answer. (The line in the `NAMESPACE` file is actually in many ways the more important of the two, though both are needed for a package on CRAN.) If for some reason the package maintainers still want **grid** to be attached (as well as imported), I'm 95% sure they would do *that* by leaving it as a `Depends:` in the `DESCRIPTION` file. (The only other possibility is that it would be entered in both the `Depends:` and `Imports:` field in `DESCRIPTION`.) If they don't actually want **grid** to be attached, then just move it from `Depends:` to `Imports:`. – Josh O'Brien Jul 06 '16 at 17:06
  • But in **any** case, add `import(grid)` (or potentially a series of `importFrom()` directives) to the `NAMESPACE` file. – Josh O'Brien Jul 06 '16 at 17:07
  • Sorry, I think we got two solutions mixed: (1) your answer above (recompile `neuralnet` with grid import) **OR** (2) move `neuralnet` from `Imports` to `Depends` in *my* package. Both solutions seem to work. – sebastianmm Jul 06 '16 at 17:21
  • 1
    Yep. Either one works, though the first one is cleaner. (If you `Depends` on **neuralnet** in your package, after all, then anybody who wants to use functions from your package in their own package will need to `Depend` on it, attaching your package and **neuralnet** and **grid**. Pretty soon, just using one function from one package means folks have to load and attach many other packages, which is a real pain.) – Josh O'Brien Jul 06 '16 at 17:24