在ggplot2中将facet标签更改为数学公式

时间:2012-08-16 00:08:52

标签: r ggplot2

我想知道如何在facet中将ggplot2标签更改为数学公式。

d <- ggplot(diamonds, aes(carat, price, fill = ..density..)) +
  xlim(0, 2) + stat_binhex(na.rm = TRUE) + opts(aspect.ratio = 1)
d + facet_wrap(~ color, ncol = 4)

enter image description here

例如,我想将facet标签从D更改为Y[1],其中1是下标。在此先感谢您的帮助。

我发现了这个answer,但它对我不起作用。我正在使用R 2.15.1ggplot2 0.9.1

5 个答案:

答案 0 :(得分:23)

您可以编辑gtable中的grobs,

ggplot(diamonds, aes(carat, price, fill = ..density..)) +
  xlim(0, 2) + stat_binhex(na.rm = TRUE) + facet_wrap(~ color, ncol = 4)


for(ii in 1:7)
grid.gedit(gPath(paste0("strip_t-", ii), "strip.text"), 
           grep=TRUE, label=bquote(gamma[.(ii)]))

enter image description here

或者,如果你想保存一个grob,

g <- ggplotGrob(d)
gg <- g$grobs

strips <- grep("strip_t", names(gg))
for(ii in strips)
  gg[[ii]] <- editGrob(getGrob(gg[[ii]], "strip.text", 
                               grep=TRUE, global=TRUE), 
                       label=bquote(gamma[.(ii)]))

g$grobs <- gg

使用ggsave会需要额外的(丑陋的)工作,因为必须愚弄ggplot类的测试...我认为明确地调用pdf() ; grid.draw(g); dev.off()会更容易。


罗兰编辑:

我做了一个小修正并将其包裹在一个函数中:

facet_wrap_labeller <- function(gg.plot,labels=NULL) {
  #works with R 3.0.1 and ggplot2 0.9.3.1
  require(gridExtra)

  g <- ggplotGrob(gg.plot)
  gg <- g$grobs      
  strips <- grep("strip_t", names(gg))

  for(ii in seq_along(labels))  {
    modgrob <- getGrob(gg[[strips[ii]]], "strip.text", 
                       grep=TRUE, global=TRUE)
    gg[[strips[ii]]]$children[[modgrob$name]] <- editGrob(modgrob,label=labels[ii])
  }

  g$grobs <- gg
  class(g) = c("arrange", "ggplot",class(g)) 
  g
}

这样可以很好地打印,甚至可以使用ggsave

答案 1 :(得分:12)

也许有人在某些时候改变了编辑Grob功能的名称。 (Edit: It was removed by @hadley about 8 months ago.) pkg:grid没有geditGrob但只有editGrob似乎有效:

 d <- ggplot(diamonds, aes(carat, price, fill = ..density..)) +
              xlim(0, 2) + stat_binhex(na.rm = TRUE) + opts(aspect.ratio = 1)

 #Note: changes in ggplot2 functions cause this to fail from the very beginning now.
 # Frank Harrell's answer this year suggests `facet_warp` now accepts `labeller`


 d <- d + facet_wrap(~ color, ncol = 4)
 grob <- ggplotGrob(d)
 strip_elem <- grid.ls(getGrob(grob, "strip.text.x", grep=TRUE, global=TRUE))$name
#strip.text.x.text.1535
#strip.text.x.text.1541
#strip.text.x.text.1547
#strip.text.x.text.1553
#strip.text.x.text.1559
#strip.text.x.text.1565
#strip.text.x.text.1571
grob <- editGrob(grob, strip_elem[1], label=expression(Y[1]))
grid.draw(grob)

答案 2 :(得分:7)

刚刚从roland和baptiste遇到了这个非常有用的函数,但是需要一个稍微不同的用例,其中原始的包装头应该由函数转换而不是作为固定值提供。我发布了原始功能的略微修改版本,以防它对其他任何人有用。它允许对包装条使用命名(固定值)表达式,以及使用自定义函数和ggplot2已为facet_grid labeller参数提供的函数(例如{{1 }和label_parsed)。

label_bquote

更新/警告

对于较新版本的facet_wrap_labeller <- function(gg.plot, labels = NULL, labeller = label_value) { #works with R 3.1.2 and ggplot2 1.0.1 require(gridExtra) # old labels g <- ggplotGrob(gg.plot) gg <- g$grobs strips <- grep("strip_t", names(gg)) modgrobs <- lapply(strips, function(i) { getGrob(gg[[i]], "strip.text", grep=TRUE, global=TRUE) }) old_labels <- sapply(modgrobs, function(i) i$label) # find new labels if (is.null(labels)) # no labels given, use labeller function new_labels <- labeller(names(gg.plot$facet$facets), old_labels) else if (is.null(names(labels))) # unnamed list of labels, take them in order new_labels <- as.list(labels) else { # named list of labels, go by name where provided, otherwise keep old new_labels <- sapply(as.list(old_labels), function(i) { if (!is.null(labels[[i]])) labels[[i]] else i }) } # replace labels for(i in 1:length(strips)) { gg[[strips[i]]]$children[[modgrobs[[i]]$name]] <- editGrob(modgrobs[[i]], label=new_labels[[i]]) } g$grobs <- gg class(g) = c("arrange", "ggplot",class(g)) return(g) } 软件包,运行此函数时会出现错误gridExtra,因为Error: No layers in plot已不在arrange而R尝试将其解释为gridExtra。您可以通过(重新)为ggplot类引入print函数来解决此问题:

arrange

现在应该允许渲染图,您可以使用print.arrange <- function(x){ grid::grid.draw(x) } 例如像这样:ggsave()

实施例

一些用例示例:

ggsave("test.pdf", plot = facet_wrap_labeller(p, labeller = label_parsed))

答案 3 :(得分:5)

截至ggplot2已为labeller实施了2.1.0 facet_wrap

答案 4 :(得分:0)

感谢您提到 label_parsed 的其他答案和评论。仍然不清楚如何使用标签解析器,所以我在这里添加了一个简单的可重现示例。

library(dplyr)
library(ggplot2)

# Create a first facet variable with examples of math formulas
iris2 <- iris %>%
    mutate(species_math = factor(Species,
                            levels = c("setosa", "versicolor", "virginica"),
                            labels = c("m^2",
                                       expression(bar(x) == sum(frac(x[i], n), i==1, n) * beta * Q[t-1]),
                                       bquote(pi == .(pi)))))

# Create a second facet variable with mean lengths
# This illustrates how to pass a numeric vector inside a formula
iris_mean <- iris2 %>%
    group_by(Species) %>%
    summarise(across(ends_with("Length"), mean), .groups="drop")

iris2$mean_length <- factor(iris2$Species,
                           levels =  c("setosa", "versicolor", "virginica"),
                           labels = mapply(function(p, s) bquote(bar(p) == .(p) ~ bar(s) ==.(s)),
                                            round(iris_mean$Petal.Length,3), round(iris_mean$Sepal.Length,3)))


iris2 %>%
    ggplot(aes(x = Petal.Length, y = Petal.Width)) +
    geom_point() +
    facet_wrap(species_math ~ mean_length + Species, labeller = labeller(species_math = label_parsed, mean_length = label_parsed))

ggsave("~/downloads/formula_in_facet.png",
       width = 12, height = 8, units = "cm")

enter image description here

如上例所示,labeller 可以解析:

  1. 简单公式的字符向量,例如“m^2”
  2. 一个 expression 用于更复杂的数学索引
  3. bquote 的输出以在公式中包含数值。另请参阅 this answer,了解如何将 bquote 用于具有多个值的数值向量。
  4. 请参阅 this other answer 了解如何仅将标签应用于分面变量之一。在我们的例子中,我们仅将其应用于 species_math 变量。

语法与 Latex 数学公式不同,因为 label_parsed 将标签解释为 plotmath 表达式。例如,在 Latex 中索引写为 x_i,在绘图数学表达式中写为 x[i],希腊字母直接写为 alpha 而不是 Latex 中的 \alpha。您可以在 plotmath 函数的帮助页面中找到许多公式。祝 plotmath 示例好运。