1

I'm not happy with scales::percent, for example, scales::percent(21/80) returns "26.2%" while I'd prefer getting "26.25%". So I wrote a quick function:

custom_percent <- function(x, digits = 2) {
  paste0(round(100 * x, digits = digits), "%")
}

However, when I try to use it with ggplot2, I receive the following error "Error in eval(expr, envir, enclos) : could not find function "custom_percent". Here is an example:

dset <- data.frame(data = 10:90)
p <- ggplot(dset, aes(x = data))
p + geom_bar(aes(y = (..count..)/sum(..count..)), width = .5) +
  geom_text(aes(y = ((..count..)/sum(..count..)),
            label = custom_percent((..count..)/sum(..count..))),
            stat = "count", vjust = -0.25) +
  scale_y_continuous(labels = custom_percent)

What can I do to access custom_percent?

5
  • I'm not sure if it's a problem with ggplot not being able to find the custom function. For example, d <- data.frame(x=1:10, y=rnorm(10)) and then ggplot(d) + geom_text(aes(x, y, label = custom_percent(y))) works perfectly fine. Commented Oct 23, 2016 at 0:23
  • It seems like a problem that's specific to using the special variables (like ..count..) together with a custom function. Interesting. Commented Oct 23, 2016 at 0:34
  • It was unexpected as when I used scales::percent everywhere instead, it just worked. But then scales was by the same author who wrote ggplot2 so maybe he used a trick in both. Commented Oct 23, 2016 at 7:07
  • it sounded like setting an environment should have helped, but it doesn't appear to work Commented Oct 23, 2016 at 19:58
  • Hi @baptiste, actually, given all the questions about capturing arguments or local variables in aes, that was the first path I tried. And of course it miserably failed. Maybe because, in my case, the ggplot and aes calls were not inside a function definition. Commented Oct 24, 2016 at 7:06

1 Answer 1

2

aes_q and bquote can help with these tricky scoping issues,

dset <- data.frame(data = 10:90)
p <- ggplot(dset, aes(x = data))
p + geom_bar(aes_(y = ~(..count..)/sum(..count..)), width = .5) +
  geom_text(aes_(y = ~((..count..)/sum(..count..)),
                label = bquote(.(custom_percent)((..count..)/sum(..count..)))),
            stat = "count", vjust = -0.25) +
  scale_y_continuous(labels = custom_percent)
Sign up to request clarification or add additional context in comments.

5 Comments

I think aes_string() would solve this in a similar way too. With the whole expression in quotes.
@BrandonBertelsen what is this, Matlab? ;)
Ugly, but functional, just_like_matlab.
@baptiste So is it aes_ or aes_q? What's the difference? Was this family of functions (and bquote as well) recently introduced?
@baptiste I accepted your answer but truly, there should be a better way to do it. Anyway, a plain aes call seems to stumble upon using the special stats ..some_stat... By the way, do you know where all these special stats are listed?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.