如何通过带引号的表达式将变量传递给使用该值返回函数的函数?

时间:2018-04-08 22:55:55

标签: r ggplot2 tidyverse tidyeval non-standard-evaluation

以下是一个例子:

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')

该功能在这样的环境之外正常工作,但为了与ggplot一起使用,必须以某种方式引用它。

不幸的是,我无法弄清楚如何正确返回包含以这种方式传递的变量的生成函数。我试过这个:

custom_percent <- function(n){
    n = enquo(n)
    function(x){
         return(paste(percent(x), sprintf('(%d)', round(x* (!!n)))))
    }
 }

但是当我这样做时出现错误:Error in !n : invalid argument type

是否有人知道如何在n返回的函数中正确使用custom_percent()的所需值?

在有人要求之前,我知道我可以事先在摘要数据框中生成统计数据使用utils::getAnywhere()作为解决方法,但这不是问题的重点。

2 个答案:

答案 0 :(得分:1)

问题不是你的功能 - 看起来很好,就像最初写的一样。您在geom_text调用中缺少括号,我认为这是主要问题。

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')

我认为这可以让你获得你想要的东西(并且在其中投掷..prop..也是如此,这对于这些数据来说只是平坦的1 - 这对我来说没有意义。如果这是你想要/期望的,那么意味着将其切换回来。您可以查看https://sebastiansauer.github.io/percentage_plot_ggplot2_V2/ - 显示您可以使用..prop....count..的位置,但这并不能解释原因。

你可以做的另一件事(利用书写的..prop..):

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)

答案 1 :(得分:0)

您可以使用基础r 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))))

n

如您所见,3已替换为class myCell: UITableViewCell { var withSeparator: Bool = true func layoutSubviews() { super.layoutSubviews() if !withSeparator { self.removeBottomSeparator() } } ... extension UITableViewCell { func removeBottomSeparator() { // Remove it if it's found. for view in self.subviews where String(describing: type(of: view)).hasSuffix("SeparatorView") { view.removeFromSuperview() } } } 。你可以试试任何其他号码。它会起作用