ggplot在函数内部无法正常工作,尽管在函数外部可以正常工作 - R

5
我正在尝试创建一个函数,该函数接受2个参数并输出相应的ggplot。手动代码完美运行,但是在函数包装器内无法运行。

返回的错误是:

Error in eval(expr, envir, enclos) : object 'TimeVector' not found

我尝试通过将未找到的对象强制转换为字符串来进行纠正,这些对象被添加到ggplot中。然而,这反过来会产生不同形式的麻烦。

Error: Discrete value supplied to continuous scale

去掉 scale_x_continuous(breaks=0:24) 后可以解决第二个错误,但是会输出一个空图表,这表明 ggplot 没有得到任何数据。

数据是一个按时间分组的交通密度观测值的大型数据框,如下所示:

ID                   Road Status                Time Statusint Day  Months Year Weekday

1 Me7war To Sheikh Zayid Orange 2012-10-01 00:03:00         3   1 October   12  Monday
1 Me7war To Sheikh Zayid  Green 2012-10-01 05:00:00         2   1 October   12  Monday
1 Me7war To Sheikh Zayid Yellow 2012-10-01 05:24:00         5   1 October   12  Monday

我正在尝试绘制“Statusint”变量(表示状态整数,范围从1(良好交通)到5(糟糕交通))与“Time”变量的关系。 "时间"格式为Posix,因此我创建了一个名为"TimeVector"的数字向量,仅用于在ggplot中绘图。
函数如下:
Plotroad <- function( roadID , Day ) {

  *** Working Code ***

  else { 

  ### THE PROBLEM CODE: Everything below works manually, but returns an error in the function

    Roadsubset <- October[October$ID == as.numeric(roadID), ] 
    Timesubset <- subset(Roadsubset, format(Roadsubset$Time,'%d') == "Day" )
    TimeVector <- as.numeric(gsub(":" , "." , strftime(Timesubset$Time, format="%H:%M")))

    ggplot(Timesubset, aes( x = "TimeVector", y = "Timesubset$Statusint")) + geom_point() +  
        stat_smooth() + scale_x_continuous(breaks=0:24) 


    ### The working code: 
    Roadsubset <- October[October$ID == as.numeric(roadID), ] 
    Timesubset <- subset(Roadsubset, subset = Roadsubset$Day == as.integer(Date) )
    TimeVector <- as.numeric(gsub(":" , "." , strftime(Timesubset$Time, format="%H:%M")))
    Timesubset$timevector <- TimeVector

    print(ggplot( data = Timesubset, aes_string( x = "timevector" , y = "Statusint" )) + geom_point() + stat_smooth()  + scale_x_continuous(breaks=0:24) + labs(list(title = as.character(Timesubset$Road[1]) , x = "Time of Day", y = "Status")))  

  }
}

我看到一些建议建议使用print,因为ggplot不是在命令行中调用的。然而,这并不能解决上述的错误。
这是我在stackoverflow上的第一个帖子,请指出我如何更好地为将来格式化问题。谢谢。

1
简而言之,但看起来你正在寻找aes_string - Roland
@Roland 谢谢,但这反过来又产生了一个新的错误: Error in parse(text = x)[[1]] : subscript out of bounds - M. Momtaz Hegazy
尝试将这个代码aes( x = "TimeVector", y = "Timesubset$Statusint"))改成 aes_string( x = "TimeVector", y = "Statusint")),我认为你不应该在aes()函数中一直添加数据引用。这里有一个类似的问题 - marbel
尝试使用一个包含所有数据的data.frame,采用长格式。同时查看这个问题,了解如何创建可重现的示例。 - marbel
1
@MartínBel 做这两件事情对我帮助很大,谢谢。 - M. Momtaz Hegazy
1个回答

7

除了使用变量名之外,作用域也是一个问题。GGPlot在全局环境中执行非标准评估,因此在函数中定义的任何内容都不会直接访问,除了“data”参数,因为该参数是通过显式传递而不是通过非标准评估传递的。因此,解决这个问题的一个方法是将变量添加到数据参数中。我创建了一个示例,我认为它模仿了您的问题,但由于我没有您的数据,因此它并不完全相同:

gg_fun <- function() {
  data <- data.frame(a=1:10, b=1:10)
  clr <- rep(c("a", "b"), 5)
  ggplot(data, aes(x=a, y=b, color=clr)) + geom_point()
}
gg_fun()
# Error in eval(expr, envir, enclos) : object 'clr' not found
gg_fun <- function() {
  data <- data.frame(a=1:10, b=1:10)
  clr <- rep(c("a", "b"), 5)
  data$clr <- clr
  ggplot(data, aes(x=a, y=b, color=clr)) + geom_point()
}
gg_fun() # works

在您的情况下,您需要将 TimeVector 添加到 Timesubset(很简单),然后使用未引用的 aes 语法:

ggplot(Timesubset, aes(x=TimeVector, y=Statusint)) ...

是的,那似乎就是这样。谢谢。 - M. Momtaz Hegazy
我遇到了与ggplot无法找到我的颜色向量类似的问题,但是我的颜色向量有四个值,与数据框中的四个因子匹配,该数据框有1200个观测值。我的数据框不允许我将一个四项向量添加为列。针对这种情况有什么修改方法吗?还是需要提出另一个问题? - mightypile
@mightypile,只需创建一个与您的数据框相同长度的向量,并为每行设置所需的颜色。match 可能有助于完成这项任务。 - BrodieG
@BrodieG,这样做会产生“错误:集合美学的长度不兼容:颜色、大小、水平对齐、垂直对齐、x、y、标签”。我已经尝试了十几种不同的颜色和标签。我认为我只需要重构和清理一下代码。更优雅的解决方案等待着我的努力。谢谢! - mightypile
1
@BrodieG 我认为使用“与你的数据框相同长度”这一术语可能会具有误导性。几乎总是要创建一个与数据框行数相同长度的向量。 - IRTFM
0-1(绕过评论审查程序)是为了追求完美主义者;),但当然你是正确的@IRTFM。顺便说一句,很不错的手柄BTW。 - BrodieG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接