34

I have a number of bash scripts which invoke R scripts for plotting things. Something like:

#!/bin/bash
R --vanilla --slave <<RSCRIPT
cat("Plotting $1 to $2\n")
input <- read.table("$1")
png("$2")
plot(as.numeric(input[1,]))
dev.off()
RSCRIPT

The problem is that despite --slave, the call to dev.off() prints the message null device 1. Once there are a lot of plots being done, or for more complex scripts which plot to a number of files, this gets to be a real hassle.

Is there some way to suppress this message?

Karolis Koncevičius
  • 9,417
  • 9
  • 56
  • 89
blahdiblah
  • 33,069
  • 21
  • 98
  • 152

5 Answers5

44

For no good reason I'm aware of, dev.off(), unlike device related functions like png() returns a value: "the number and name of the new active device." That value is what's being echoed to stdout.

Suppressing it can thus be achieved by just putting it somewhere, i.e.,

garbage <- dev.off()
blahdiblah
  • 33,069
  • 21
  • 98
  • 152
20

One of the nice things about R is that you can view the source of many functions:

> dev.off
function (which = dev.cur()) 
{
    if (which == 1) 
        stop("cannot shut down device 1 (the null device)")
    .Internal(dev.off(as.integer(which)))
    dev.cur()
}
<environment: namespace:grDevices>

So it calls .Internal(dev.off(...)) and then returns dev.cur(), which I suppose would be useful if you have several devices open so you know which one became active. You could use .Internal(dev.off(as.integer(dev.cur()))) in your script, or even patch dev.off to only return the value of dev.cur() if it is something else than the null device, and send the patch to the maintainers of R.

Also, graphics.off() calls dev.off() for all devices and doesn't return anything.

Jouni K. Seppänen
  • 43,139
  • 5
  • 71
  • 100
12

Ran into the same issue recently and noticed that one more possibility is not mentioned in the answers here:

invisible(dev.off())

This will hide the output from dev.off() and will not create additional variables unlike assigning the output to garbage variable: garbage <- def.off() would.

Karolis Koncevičius
  • 9,417
  • 9
  • 56
  • 89
2

You can use littler instead which is a) an easier way to write R 'scripts' and b) suppresses output so you get the side effect of dev.off being silent:

$ foo.r /tmp/foo.txt /tmp/foo.png
Plotting /tmp/foo.txt to /tmp/foo.png
$ cat /tmp/foo.r
#!/usr/bin/r
cat("Plotting", argv[1], "to", argv[2], "\n")
input <- read.table(argv[1])
png(argv[2])
plot(as.numeric(input[1,]))
dev.off()
$

Rscript will probably work too; I tend to prefer littler.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • nice to know about this. but it requires more modifying of the Rscript source. For example, normal variable printing by just giving the variable name will also be silent by default. – biocyberman Sep 25 '16 at 11:30
2

Another option would be to use sink() and output everything to a log file, so you can check up on whether the plots worked if you need to.

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
David Lawrence Miller
  • 1,801
  • 11
  • 12