ggplot2 + aes_string通过公式接口在函数内部

时间:2013-02-07 01:56:35

标签: r ggplot2 facet

交互式地,这个例子工作正常:

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")无效。建议?我不断被这些事情所困扰。谢谢!

2 个答案:

答案 0 :(得分:6)

您可以使用as.formulapaste

p <- p + facet_grid(as.formula(paste(". ~", fac2)))

在您的示例中,这给出了:

enter image description here

答案 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)

enter image description here