How to suppress qplot's binwidth warning inside a function? - r

I am writing a function that uses qplot() to draw a histogram, for example,
> library(ggplot2)
> d=rnorm(100)
> myfun=function(x) qplot(x)
Running it gives a warning:
> myfun(d)
stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.
To suppress the warning, I tried computing the binwidth myself, but this gives an error and doesn't plot:
> myfun=function(x) print(qplot(x, binwidth=diff(range(x))/30))
> myfun(d)
Error in diff(range(x)) : object 'x' not found
I have two related questions:
What is going on here? Why is object 'x' not found?
How can I write the function so the warning is not generated?
Thanks!

To attempt to clear up some confusion, this construct does not prevent the binwidth warnings/messages to appear:
suppressMessages(p <- ggplot(...))
print(p)
But this does:
p <- ggplot(...)
suppressMessages(print(p))
As Hadley's comment points out, lazy evaluation prevents the stat_* functions from actually running until they need to at print-time.

I can't explain the why of this one (Hadley may swing by and do so) but using ggplot instead of qplot solves the problem:
d <- data.frame(v1 = rnorm(100))
myfun <- function(x){
p <- ggplot(data = x, aes(x = v1)) +
geom_histogram(binwidth = diff(range(x$v1))/30)
print(p)
}
Doing it this way I get no warning message. Also, using ggplot and removing the binwidth = ... portion in geom_histogram makes the warning reappear, but then suppressMessages works as expected as well.
I suspect this has to do with namespaces or environments and when/where qplot and ggplot are evaluating arguments. But again, that's just a guess...

As they say on TV "Had this been a real warning you would have been given directions from your local authorities."
Since it wasn't a warning then my original answer didn't cause it to error out. This is what I should have written:
options(warnings= -1)
<do something> # no warnings
options(warnngs=1)
<business as usual>
But it wasn't a warning but a message to the console. Here's how to stop it:
con=file("temp.fil", "w")
sink(con, type="message")
library(ggplot2)
d=rnorm(100)
myfun=function(x) qplot(x)
myfun(d)
sink( type="message")

Related

Error when using "panel.ellipse" function in R

I want to draw a confidence ellipse. I search the R document and find the function: panel.ellipse. Here is the description website
Then I tried. I used the code below:
library(corrgram)
a<-c(1,2,3,4,5)
b<-c(2,4,6,5,3)
panel.ellipse(a, b)
But an error occur:
Error in plot.xy(xy.coords(x, y), type = type, ...) :
plot.new has not been called yet
I didn't call "plot.new", why did R say that?
You're linking to the latticeExtra::panel.ellipse function in the description link, but seem to be using corrgram which also has a panel.ellipse function. So I'm not sure which panel.ellipse function you are using/want to use.
From ?corrgram::panel.ellipse:
# CAUTION: The latticeExtra package also has a 'panel.ellipse' function
# that clashes with the same-named function in corrgram. In order to us
# the right one, the example below uses 'lower.panel=corrgram::panel.ellipse'.
# If you do not have latticeExtra loaded, you can just use
# 'lower.panel=panel.ellipse'.
Why not use ggplot2::stat_ellipse instead?
# Your sample data
a<-c(1,2,3,4,5)
b<-c(2,4,6,5,3)
df <- cbind.data.frame(a, b);
# Use stat_ellipse to draw confidence ellipse
require(ggplot2);
ggplot(df, aes(a, b)) + geom_point() + stat_ellipse();

cbind on ggplotGrob objects fails with "Error in mmm < each : comparison of these types is not implemented"

This appears to be similar to an issue that #baptiste was trying to work around back in 2014. I am revisiting code I wrote back in June that involved creating three ggplotGrobs and combining them with a call to cbind. Now, this code fails with the message: "Error in mmm < each : comparison of these types is not implemented."
I thought that this would be specific to my particular application, but I was able to make a very simple, reproducible example. Even if the cbind is performed on two identical ggplotGrobs, this code still fails.
library(ggplot2)
library(gtable)
# Make some plots
pl1 <- ggplot(mtcars, aes(x = disp, y = mpg)) +
geom_point()
pl2 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, colour = Species)) +
geom_point()
# Convert to grobs
pl1_grob <- ggplotGrob(pl1)
pl2_grob <- ggplotGrob(pl2)
# Bind them together -- Error!
combined_grob <- cbind(pl1_grob, pl2_grob)
The error and relevant traceback are here:
> combined_grob <- cbind(pl1_grob, pl2_grob)
Error in mmm < each : comparison of these types is not implemented
> traceback()
8: comp(x_val, y_val)
7: unit(comp(x_val, y_val), x_unit)
6: compare_unit(x$heights, y$heights, pmax)
5: cbind_gtable(x, y, size = size)
4: f(init, x[[i]])
3: Reduce(function(x, y) cbind_gtable(x, y, size = size), gtables)
2: cbind(deparse.level, ...)
1: cbind(pl1_grob, pl2_grob)
This code fails with R-3.4.2 on OS X 10.11.6 with grid_3.4.2, gtable_0.2.0, and ggplot2_2.2.1, AND with R-3.3.2 on Linux (compiled from source on Ubuntu 16.04) with grid_3.3.2, gtable_0.2.0, and ggplot2_2.2.1.
Before making the example above, I noticed that one of the vignettes in the "lemon" package ("gtable_show_lemonade") fails near the very end with the same error upon a cbind of two gtables. I confirmed this error by running the code for this vignette from source, which goes something like:
library(lemon)
edit(vignette('gtable_show_lemonade', package = 'lemon'))
# Then use whichever editor you opened to copy the temporary filename
# of the vignette source, and run this with source()
The compiled vignette (with failed cbind) is here: https://cran.r-project.org/web/packages/lemon/vignettes/gtable_show_lemonade.html
The failure during vignette compilation was obtained using the aforementioned R-3.4.2 instance running on OS X 10.11 (El Capitan).
I would appreciate any help with working around this! Since I would like to use my Mac to generate the figures (better font situation), I'm hoping there is a way I can overload a function to fix this.
UPDATE:
This is "only" a problem if size = 'max', which is the default, is specified (or size = 'min'). I think that I can work around it using size = 'first' or size = 'last', which do not perform the offending height comparisons, but it is certainly not convenient that the default behavior doesn't work (and there are certain situations size = 'max' is useful).
I never managed to get this fixed in gtable so gridExtra has a modified version called gtable_cbind.

gridsvg does not work when used inside a function

I want to define a plot saving function that uses the gridsvg device from the package gridSVG.
library(ggplot2)
library(gridExtra)
mtcars$gear <- factor(mtcars$gear,levels=c(3,4,5),
labels=c("3gears","4gears","5gears"))
mtcars$am <- factor(mtcars$am,levels=c(0,1),
labels=c("Automatic","Manual"))
mtcars$cyl <- factor(mtcars$cyl,levels=c(4,6,8),
labels=c("4cyl","6cyl","8cyl"))
myPlot <- qplot(mpg, data=mtcars, geom="density", fill=gear, alpha=I(.5),
main="Distribution of Gas Milage", xlab="Miles Per Gallon",
ylab="Density")
savePlot <- function(filename, plot, plotWidth = 15, plotHeight = 10){
gridSVG:::gridsvg(name = filename, width = plotWidth, height = plotHeight)
print(plot)
dev.off(which = dev.cur())
}
However if I then try to use the function it does not work. An error results:
savePlot("~/Desktop/myplot.svg", myPlot)
Show Traceback
Rerun with Debug
Error in eval(expr, envir, enclos) : object 'filename' not found
However if I do those steps from the console it works:
gridSVG::gridsvg(name = "~/Desktop/myPlot.svg", width = 15, height = 10)
myPlot
dev.off()
Is there a way I might be able to use the gridsvg function from within another function?
I wonder if I might be able to do it with eval from some environment.
Thanks,
Ben.
Here's a roundabout, but slightly more principled, way without sticking everything in the global environment (inspired by the scoping discussion in R Inferno):
library(gridSVG)
savePlot <- function(filename, plot, plotWidth = 15, plotHeight = 10){
gridsvg(sys.frame(1))
print(plot)
grid.export(filename)
grDevices::dev.off(which = dev.cur())
}
sys.frame(1) gives us the evaluation frame of the parent context (there's an ok explanation here for all variations on functions that access the call stack).
I separated out the call to grid.export() from the call to dev.off(), because essentially all the dev.off from gridSVG does is call grid.export, then call the grDevices::dev.off. This also lets us explicitly feed the file name to grid.export.
How curious. gridsvg seems to have an eval(fncall[[i]]) step where it walks through all the arguments and assigns them, and it must be looking in the wrong environment or something?? I am not sure if this is a problem with the gridSVG package; eval-semantics always confuse me.
Here's a workaround: if you make sure the argument -values- get passed to gridsvg (rather than the argument names) it works, though I agree this isn't particularly elegant. And you have to explicitly library(gridSVG).
library(gridSVG)
savePlot <- function(filename, plot, plotWidth = 15, plotHeight = 10){
eval(call('gridsvg', name=filename, width=plotWidth, height=plotHeight))
print(plot)
dev.off(which = dev.cur())
}
All it does is essentially call gridsvg with width=15 rather than width=plotWidth and so on.

parallel coord plot ggplot2 deprecated?

When i try to make a parallel coordinate in ggplot2, i get the message that it is deprecated:
require(ggplot2)
ggpcp(mtcars) + geom_line()
Warning message:
'ggpcp' is deprecated.
See help("Deprecated")
however, the ggplot documentation did not say anything about this: http://docs.ggplot2.org/current/ggpcp.html.
is there a new pcp function somewhere?
Migrated to GGally. E.g.:
require(GGally)
ggparcoord(mtcars, columns = c(1, 5:10)) + geom_line()

ggplot "error in rename"

update I have posted my solution below, the culprit was my own rename function that overrode reshape::rename
I have been using the ggplot R package with little trouble until today. Today, I get an error using code that has previously worked, and when I debug it to the minimal working example, it still gives an error;
If I do this:
library(ggplot2)
d<- data.frame(x=1:3,y=1:3)
ggplot(data=d) + geom_line(aes(x,y))
The following error is returned:
Error in rename(x, .base_to_ggplot) :
unused argument(s) (.base_to_ggplot)
The traceback is:
6: rename(x, .base_to_ggplot)
5: rename_aes(aes)
4: aes()
3: structure(list(data = data, layers = list(), scales = Scales$new(),
mapping = mapping, options = list(), coordinates = CoordCartesian$new(),
facet = FacetGrid$new(), plot_env = environment), class = "ggplot")
2: ggplot.data.frame(data = d, aes = c(x, y))
1: ggplot(data = d, aes = c(x, y))
The error does not occur after removing all objects using rm(list=ls()), but it is still not clear to me what object is causing this error or why - how can I figure this out?
Does anyone know what may have gone wrong?
I'm not able to return the same error message that you've posted above. When running your code snippet, I'm getting the following error:
Error: geom_pointrange requires the following missing aesthetics: ymin, ymax
Accordingly, geom_pointrange() is expecting arguments for ymin and ymax. I'll leave it up to you to fill in your pertinent information for what should go into those parameters, but this code executes:
ggplot(data=d) + geom_pointrange(aes(x,y, ymin = y - .5, ymax = y + .5))
The problem is caused because ggplot2 doesn't use namespaces - this will be fixed in the next release.
The error was caused by one of the objects (thanks to pointers from #Chase).
Here is how I debugged and found the culprit. The important part was to use the try() function that keeps the for loop running despite errors
foo <- ls() #get a static list of all suspect objects
for(i in 1:length(foo)) {
print(foo[i])
rm(list=foo[i])
try(ggplot()+geom_point(aes(x=1:2,y=1:2)))
}
This resulted in the following output:
...
[1] "45 reg.model"
Error in rename(x, .base_to_ggplot) :
unused argument(s) (.base_to_ggplot)
[1] "46 reg.parms"
Error in rename(x, .base_to_ggplot) :
unused argument(s) (.base_to_ggplot)
[1] "47 rename"
[1] "48 samples"
...
aha! it was my own function rename that caused the error, since ggplot2 relies on reshape::rename.
Solution: rename the new rename function... how to prevent this in the future? Perhaps study up on the use of namespaces.

Resources