Interactively, this example works fine:
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + facet_grid(. ~ vs)
Now, make a function with a formula interface and use aes_string
to do this same thing, and it doesn't work (error is: Error in layout_base(data, cols, drop = drop) : At least one layer must contain all variables used for facetting
):
tf <- function(formula, data) {
res <- as.character(formula[[2]])
fac2 <- as.character(formula[[3]][3])
fac1 <- as.character(formula[[3]][2])
# p <- ggplot(aes_string(x = fac1, y = res), data = data)
# p <- p + geom_point() # original attempt
p <- ggplot() # This is Joran's trick, but it doesn't work here
p <- p + geom_point(aes_string(x = fac1, y = res), data = data)
p <- p + facet_grid(.~fac2) # comment this out, and it works but
# of course is not faceted
}
p <- tf(formula = wt ~ am*vs, data = mtcars)
By Joran's trick I refer to here, which is a similar question I posted recently. In this case ggplot2
doesn't see my faceting request. Making it facet_grid(".~fac2")
had no effect. Suggestions? I'm continually out-witted by these things. Thanks!
You can use as.formula
and paste
:
p <- p + facet_grid(as.formula(paste(". ~", fac2)))
In your example, this gives:
I have used formula.tools
for manipulating formulae.
I think you should have a separate argument for the faceting formula, otherwise you will have to create your own parser to work out what wt ~ am*vs
means in terms of faceting
something like the lattice grouping idea might be useful
wt~am | vs
but you would have to delve into lattice to see how they parse their formulas (look atlatticeParseFormula
- complicated!)
Easier just to separate the two formulae. You can pass a list of character variables as rhs and lhs for the facet
argument to facet_grid
I've also used environment = parent.frame()
which works in my small testing
library(formula.tools)
tf <- function(formula, faceting = NULL, data, print = TRUE) {
y <- rhs(formula)
x <- lhs(formula)
p <- ggplot(environment = parent.frame())
p <- p + geom_point(aes_string(x = x, y = y), data = data)
if (! is.null(faceting)){
rhsfacet <- all.vars(rhs(faceting))
lhsfacet <- all.vars(lhs(faceting))
if(length(lhsfacet)==1 & any(lhsfacet %in% '.')) {lhsfacet <- NULL}
if(length(rhsfacet)==1 & any(rhsfacet %in% '.')) {rhsfacet <- NULL}
p <- p+ facet_grid(facet = list( lhsfacet, rhsfacet))}
if(print) {print(p)}
p
}
tf(wt~mpg, faceting = ~am, data = mtcars, print = TRUE)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With