Reputation: 4385
Here's an example:
library(ggplot2)
library(scales) # for percent() function
custom_percent <- function(n){
function(x){
return(paste(percent(x), sprintf('(%d)', round(x* (n)))))
}
}
mydata = data.frame(x = rep(c('a','b','c'), each=100))
ggplot(mydata) + geom_text(aes_(x=~x, y=~..prop..,
label=bquote(.(custom_percent)(length(x))(..prop..)),
stat='count')
The function works properly outside of such an environment, but in order to use it with ggplot
, it has to be quoted in one way or another.
Unfortunately, I can't figure out how to properly return a generated function that contains a variable that is passed in such a manner. I've tried this:
custom_percent <- function(n){
n = enquo(n)
function(x){
return(paste(percent(x), sprintf('(%d)', round(x* (!!n)))))
}
}
But I get an error when I do this: Error in !n : invalid argument type
Does anyone know how to properly use the desired value of n
in the function returned by custom_percent()
?
And before anyone asks, I know I can generate the statistics in a summary data frame beforehand or use utils::getAnywhere()
as a workaround, but that's not the point of the question.
Upvotes: 1
Views: 308
Reputation: 4551
The issue isn't your function - which looks fine as originally written. You're missing parenthesis in your geom_text call, which I think is the primary issue.
custom_percent <- function(n){
function(x){
return(paste(percent(x), sprintf('(%d)', round(x* (n)))))
}
}
# I made the data slightly more variable
mydata = data.frame(x = rep(c('a','b','c'), rbinom(3, 100, .8)))
ggplot(mydata, aes(x = x)) +
# geom_bar(stat = 'count') +
geom_text(aes_(label=bquote(.(custom_percent)(length(x))(..count.. / sum(..count..)))),
stat='count')
I think this gets you what you want (and throwing ..prop..
in there works too, it's just flat 1s for this data - which did not make sense to me. If thats what you wanted/expected, by all means switch it back. You might check out https://sebastiansauer.github.io/percentage_plot_ggplot2_V2/ - that shows where you can use ..prop..
and ..count..
, but it doesn't really explain why).
Another thing you can do (taking advantage of ..prop..
as written):
ggplot(mydata, aes(x = x, y = ..prop..), stat = 'count') +
# geom_bar(aes(y = ..prop..), stat = 'count') +
geom_text(aes_(label=bquote(.(custom_percent)(length(x))((..count..) / sum(..count..)))),
stat='count') +
scale_y_continuous(labels=scales::percent)
Upvotes: 1
Reputation: 79288
You can use the base r substitute
to capture the whole expression and then write the expression as a functionBody
custom_percent <- function(n){
n=eval(n)
m=substitute(return(paste(percent(x), sprintf('(%d)', round(x*n)))))
`functionBody<-`(function(x)1,parent.frame(),m)
}
s=3
custom_percent(s)
function (x)
return(paste(percent(x), sprintf("(%d)", round(x * 3))))
as you can see, n
has been replaced with 3
. You can try any other number. And it will work
Upvotes: 0