【问题标题】:Scoping of variables in aes(...) inside a function in ggplotggplot中函数内aes(...)中变量的范围
【发布时间】:2014-04-12 19:24:08
【问题描述】:

考虑在函数内部使用ggplot(...)

x  <- seq(1,10,by=0.1)
df <- data.frame(x,y1=x, y2=cos(2*x)/(1+x))

library(ggplot2)
gg.fun <- function(){
  i=2
  plot(ggplot(df,aes(x=x,y=df[,i]))+geom_line())
}

if(exists("i")) remove(i)
gg.fun()
# Error in `[.data.frame`(df, , i) : object 'i' not found
i=3
gg.fun()   # plots df[,3] vs. x

看起来ggplot 无法识别函数内部定义的变量i,但确实 识别i(如果它是在全局环境中定义的)。这是为什么呢?

请注意,这给出了预期的结果。

gg.new <- function(){
  i=2
  plot(ggplot(data.frame(x=df$x,y=df[,i]),aes(x,y)) + geom_line())
}
if(exists("i")) remove(i)
gg.new()   # plots df[,2] vs. x
i=3
gg.new()   # also plots df[,2] vs. x

【问题讨论】:

  • 你可以使用aes_string 来传递参数吗?
  • @RomanLuštrik - 谢谢,但我永远不会像这样使用aes(...);我会用第二种方法。我试图了解发生了什么。这是一个错误吗?或者这种行为有充分的理由吗?还是我只是做错了什么?
  • 这可能与我的问题有关吗? stackoverflow.com/questions/23482036/…我在那里试过你的方法,但没有解决。

标签: r ggplot2 nse standard-evaluation non-standard-evaluation


【解决方案1】:

让我们返回一个未渲染的ggplot 对象,看看发生了什么:

gg.str <- function() {
     i=2
     str(ggplot(df,aes(x=x,y=df[,i]))+geom_line())
}

gg.str()
List of 9
 $ data       :'data.frame':    91 obs. of  3 variables:
  ..$ x : num [1:91] 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 ...
  ..$ y1: num [1:91] 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 ...
  ..$ y2: num [1:91] -0.208 -0.28 -0.335 -0.373 -0.393 ...
 $ layers     :List of 1
  ..$ :Classes 'proto', 'environment' <environment: 0x0000000009886ca0> 
 $ scales     :Reference class 'Scales' [package "ggplot2"] with 1 fields
  ..$ scales: list()
  ..and 21 methods, of which 9 are possibly relevant:
  ..  add, clone, find, get_scales, has_scale, initialize, input, n, non_position_scales
 $ mapping    :List of 2
  ..$ x: symbol x
  ..$ y: language df[, i]
 $ theme      : list()
 $ coordinates:List of 1
  ..$ limits:List of 2
  .. ..$ x: NULL
  .. ..$ y: NULL
  ..- attr(*, "class")= chr [1:2] "cartesian" "coord"
 $ facet      :List of 1
  ..$ shrink: logi TRUE
  ..- attr(*, "class")= chr [1:2] "null" "facet"
 $ plot_env   :<environment: R_GlobalEnv> 
 $ labels     :List of 2
  ..$ x: chr "x"
  ..$ y: chr "df[, i]"
 - attr(*, "class")= chr [1:2] "gg" "ggplot"

正如我们所见,mapping for y 只是一个未计算的表达式。现在,当我们要求进行实际绘图时,表达式在plot_env 内进行评估,这是全局的。我不知道为什么这样做;我相信这是有原因的。

这是一个可以覆盖此行为的演示:

gg.envir <- function(envir=environment()) {
    i=2
    p <- ggplot(df,aes(x=x,y=df[,i]))+geom_line()
    p$plot_env <- envir
    plot(p)
}
# evaluation in local environment; ok
gg.envir() 
# evaluation in global environment (same as default); fails if no i
gg.envir(environment())

【讨论】:

    猜你喜欢
    • 2013-03-12
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 2012-10-04
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多