【问题标题】:ggplot2 + aes_string inside a function via formula interfaceggplot2 + aes_string 通过公式接口在函数内
【发布时间】:2013-01-22 10:21:12
【问题描述】:

以交互方式,此示例运行良好:

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") 无效。建议?我一直被这些事情弄得不知所措。谢谢!

【问题讨论】:

  • fac2 的示例值是什么? (它只是一个向量,还是一个更复杂的公式?)
  • fac2 就像fac1 一样,是一个字符串,它给出了一个数据框列的名称,它是一个因素或强制因素。它是可重现的,使用mtcars查看最后一行。
  • 我认为将分面公式作为第二个参数会容易得多,否则您将不得不构建一个新的解析器,但是您希望区分分面变量和坐标变量
  • @mnel,不完全确定您的意思 - 将刻面移到哪里?
  • 看我的回答。希望现在更有意义。

标签: r ggplot2 facet


【解决方案1】:

您可以使用as.formulapaste

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

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

【讨论】:

  • 该死的,我从来没有接触过的组合!谢谢。
  • 而且您甚至不需要转换为公式,p &lt;- p + facet_grid(paste(". ~", fac2)) 就可以正常工作!
【解决方案2】:

我使用formula.tools 来处理公式。

我认为你应该对分面公式有一个单独的参数,否则你将不得不创建自己的解析器来计算wt ~ am*vs 在分面方面的含义

类似点阵分组的想法可能有用

wt~am | vs

但您必须深入研究 lattice 才能了解它们如何解析公式(看看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)

【讨论】:

  • 我明白你现在的意思了。您正在使用一些我需要研究的有趣工具。我也对将列表传递给facet 的想法感兴趣,这是我以前从未见过的。刚查了一下,目前0.9.3的页面中没有记录。
  • 是的。我是通过查看源代码到达那里的。我认为有一种方法可以考虑.as.quotedplyr 中的工作方式。我还进行了编辑,使其对复杂的刻面公式(并且没有刻面)更加稳健
猜你喜欢
  • 2020-12-31
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 2022-11-04
  • 2011-05-03
  • 2020-05-21
  • 1970-01-01
相关资源
最近更新 更多