【问题标题】:ggplot2: pass factor variable to facet_wrapggplot2:将因子变量传递给 facet_wrap
【发布时间】:2020-09-14 05:41:29
【问题描述】:

我正在尝试用函数替换逐行脚本以生成 ggplot2 图形 - 但被 facet_wrap 卡住了

为了概括这个问题,我创建了这个玩具数据集 - 它为两个主题(“ID)绘制了一个随时间变化的值

day <- c(0,  3,  5,  7,  9, 14,  0,  3,  5,  7,  9, 14)
value <- c(0.0, 3.6, 6.7, 7.6, 8.7, 0.0, 0.0, 1.0, 1.2, 8.3, 1.2, 0.0)
ID <- as.factor(c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2))
df <- data.frame(ID, day, value)

使用以下脚本方法,我可以生成当日值的折线图 - 分两个主题

ggplot(df, aes(day, value)) + geom_line() + facet_wrap(~ID) 

然后我尝试通过使用此代码创建并调用函数来做到这一点:

fun <- function(data, x, y, fac){
  p <- ggplot(df, aes(x, y)) + geom_line() 
  p + facet_wrap(~fac)
}
fun(df, day, value, ID)

但我收到以下错误:

 Error: At least one layer must contain all faceting variables: `fac`.
* Plot is missing `fac`
* Layer 1 is missing `fac`

有趣的是,如果我将“ID”硬编码到函数中,一切正常 - 我什至不必传递分面变量

fun <- function(data, x, y){
  p <- ggplot(df, aes(x, y)) + geom_line() 
  p + facet_wrap(~ID)
}
fun(df, day, value) 

但是这种方式破坏了创建函数的泛化优势

如果有人能告诉我我做错了什么以及可能的解决方法,我将不胜感激

谢谢

PS。我已经检查了 StackExchange 上的答案,虽然关于 facet_wrap 有几个类似的问题,但是我无法让建议的解决方案起作用,或者不理解它们

【问题讨论】:

    标签: ggplot2 facet-wrap


    【解决方案1】:

    因为非标准评估会以微妙的方式改变范围规则,所以您不能简单地将变量提供给函数内的aes()vars() 调用(~ formula 符号包装vars())。这个问题的更详细的处理方法你可以在这里找到:https://ggplot2.tidyverse.org/articles/ggplot2-in-packages.html

    其中一个解决方案是将变量名称包装到{{...}} 中,这表明非标准评估应该使用作为参数给出的任何表达式进行,而不是参数表达式的评估值。

    library(ggplot2)
    
    day <- c(0,  3,  5,  7,  9, 14,  0,  3,  5,  7,  9, 14)
    value <- c(0.0, 3.6, 6.7, 7.6, 8.7, 0.0, 0.0, 1.0, 1.2, 8.3, 1.2, 0.0)
    ID <- as.factor(c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2))
    df <- data.frame(ID, day, value)
    
    fun <- function(data, x, y, fac){
      p <- ggplot(df, aes({{x}}, {{y}})) + geom_line() 
      p + facet_wrap(vars({{fac}}))
    }
    
    fun(df, day, value, ID)
    

    reprex package (v0.3.0) 于 2020 年 5 月 27 日创建

    另外,请注意,您还应该用双括号将 xy 变量括起来。它之前工作的唯一原因是因为dayvalue 是全局环境中的变量(长度为nrow(df))。如果在干净的环境中运行,以下会返回错误:

    library(ggplot2)
    
    df <- data.frame(
      ID = as.factor(c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2)), 
      day = c(0,  3,  5,  7,  9, 14,  0,  3,  5,  7,  9, 14), 
      value = c(0.0, 3.6, 6.7, 7.6, 8.7, 0.0, 0.0, 1.0, 1.2, 8.3, 1.2, 0.0)
    )
    
    fun <- function(data, x, y, fac){
      p <- ggplot(df, aes(x, y)) + geom_line() 
      p + facet_wrap(vars({{fac}}))
    }
    
    fun(df, day, value, ID)
    #> Error in FUN(X[[i]], ...): object 'day' not found
    

    reprex package (v0.3.0) 于 2020 年 5 月 27 日创建

    【讨论】:

    • 非常感谢您的解决方案 - 效果很好!在一百万年后我不可能解决这个问题!
    猜你喜欢
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 2021-08-12
    • 2019-10-31
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多