交互式地,这个例子工作正常:
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + facet_grid(. ~ vs)
现在,使用公式接口创建一个函数并使用aes_string
执行相同的操作,但它不起作用(错误是: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)
通过Joran的伎俩,我引用here,这是我最近发布的类似问题。在这种情况下,ggplot2
没有看到我的分面请求。使facet_grid(".~fac2")
无效。建议?我不断被这些事情所困扰。谢谢!
答案 0 :(得分:6)
您可以使用as.formula
和paste
:
p <- p + facet_grid(as.formula(paste(". ~", fac2)))
在您的示例中,这给出了:
答案 1 :(得分:6)
我使用formula.tools
来操纵公式。
我认为你应该为分面公式设置一个单独的参数,否则你必须创建自己的解析器来计算wt ~ am*vs
在分面方面的含义
像格子分组的想法可能是有用的
wt~am | vs
但你必须深入研究格子,看看他们如何解析他们的公式(看latticeParseFormula
- 复杂!)
更容易将两个公式分开。您可以将facet
参数的字符变量列表作为rhs和lhs传递给facet_grid
我还使用了environment = parent.frame()
,它可以在我的小测试中使用
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)