2

首先是一些背景。我正在尝试使用 ggplot2 创建瀑布图。我编写了以下函数来解决问题。但是,在尝试为 geom_text 标签提供用户提供的格式化功能时,我遇到了一个小问题。

plotIt<-function()
{
  require(ggplot2)
  require(scales)

  # Define formatting functions
  formatter<-function(x, ...) format(x, big.mark = ' ', trim = TRUE, scientific = FALSE, ...)
  strwr<-function(x) gsub(" ", "\n", x)

  # Build data frame to plot
  mydf<-structure(list(Description = structure(1:6, .Label = LETTERS[1:6], class = "factor"), 
                       change = c(0.86, 0.14, 0.08, -0.05, -0.03, 1.00), 
                       id = 1:6, 
                       end = c(0.86, 1.00, 1.08, 1.03, 1.00, 0.00), 
                       start = c(0, 0.86, 1.00, 1.08, 1.03, 1.00), 
                       type = structure(c(2L, 2L, 2L, 1L, 1L, 2L), .Label = c("Neg", "Pos"), class = "factor")), 
                  .Names = c("Description", "change", "id", "end", "start", "type"), 
                  row.names = LETTERS[1:6], class = "data.frame")

  # Plot it
  ggplot(mydf, aes(Description, fill = type)) + 
    geom_rect(aes(x = Description, xmin = id - 0.45, xmax = id + 0.45, ymin = end, ymax = start)) + 
    scale_y_continuous(labels = formatter) +
    scale_x_discrete("", breaks = levels(mydf$Description), labels = strwr(levels(mydf$Description))) +
    geom_text(aes(x = id, y = end, label = formatter(change)), vjust = 1, size = 3)
}

调用此函数会生成以下错误消息:

eval 中的错误(expr、envir、enclos):找不到函数“格式化程序”

罪魁祸首是最后一行 geom_text 中的 label = formatter(change) 代码。如果我用 label = comma(change) 替换它,一切正常。“逗号”功能来自 scales 包。简而言之:

geom_text(aes(x = id, y = end, label = comma(change)), vjust = 1, size = 3)

有效,但

geom_text(aes(x = id, y = end, label = formatter(change)), vjust = 1, size = 3)

才不是。

输出如下所示: Waterfall plot

Why doesn't geom_text accept my own formatting function? I'm sure it's something simple but I cannot see it.

4

2 回答 2

2

I think this is an issue with the environment in the ggplot call. If you add environment = environment(), it works:

  ggplot(mydf, aes(Description, fill = type), environment = environment()) + 
    geom_rect(aes(x = Description, xmin = id - 0.45, xmax = id + 0.45, ymin = end, ymax = start)) + 
    scale_y_continuous(labels = formatter) +
    scale_x_discrete("", breaks = levels(mydf$Description), labels = strwr(levels(mydf$Description))) +
    geom_text(aes(x = id, y = end, label = formatter(change)), vjust = 1, size = 3)

As I understand it, this is because the function from scales is available in the global environment, but since you're defining formatter inside the function plotIt(), it is not available.

You can see this by the fact that if you run your code outside a defined function (start from inside your curly brackets), it all works. That is because this puts formatter in the global environment.

As a bit more explanation, you're error message is: Error in eval(expr, envir, enclos) : could not find function "formatter". If you look at the base function eval(), the default envir argument is parent.frame(). If you look at the output from environment(), you see it's <environment: R_GlobalEnv>. So when eval() operates, this tells it to look in the right place.

于 2013-03-15T10:11:47.957 回答
0

You may also use the waterfall package. Here's a brief example showing the functionality. I think you wont have to care so much about the formatting.

于 2013-07-28T08:52:21.227 回答