ggplot2:将因子变量传递给facet_wrap [英] ggplot2: pass factor variable to facet_wrap

查看:179
本文介绍了ggplot2:将因子变量传递给facet_wrap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试替换逐行脚本以使用功能生成ggplot2图形-但没有被facet_wrap保留

为概括这个问题,我创建了这个玩具数据集-随时间绘制了两个对象("ID")的值

  day<-c(0、3、5、7、9、14、0、3、5、7、9、14)值<-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,2))df<-data.frame(ID,day,value) 

使用以下脚本编制方法,我可以生成当天值的线图-涉及两个主题

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

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

  fun<-函数(数据,x,y,fac){p<-ggplot(df,aes(x,y))+ geom_line()p + facet_wrap(〜fac)}乐趣(df,日期,值,ID) 

但是出现以下错误:

 错误:至少一层必须包含所有构面变量:fac.*情节缺少`fac`*第1层缺少`fac` 

有趣的是,如果我将"ID"硬编码到函数中,则一切正常-甚至不必传递构面变量

  fun<-函数(data,x,y){p<-ggplot(df,aes(x,y))+ geom_line()p + facet_wrap(〜ID)}乐趣(df,日期,值) 

但是这种失败破坏了创建函数的普遍意义

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

谢谢

PS.我已经在StackExchange上做了一个答案的检查,尽管关于facet_wrap有一些类似的问题,但是我无法获得建议的解决方案,或者无法理解

解决方案

由于非标准评估会以微妙的方式更改作用域规则,因此您不能简单地将变量输入 aes()函数内的vars()调用(〜公式表示法包装 vars()).您可以在这里找到有关此问题的更详细的处理方法:(v0.3.0)创建于2020-05-27 sup>

此外,请注意,您还应该将 x y 变量放在双括号中.它之前起作用的唯一原因是因为 day value 是全局环境中的变量(长度为 nrow(df)).如果在干净的环境中运行,以下内容将返回错误:

 库(ggplot2)df<-data.frame(ID = as.factor(c(1,1,1,1,1,1,2,2,2,2,2,2,2)),天= c(0,3,5,7,9,14,14,0,3,5,7,9,14),值= 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))有趣的<-函数(数据,x,y,fac){p<-ggplot(df,aes(x,y))+ geom_line()p + facet_wrap(vars({{fac}}))}乐趣(df,日期,值,ID)#>FUN(X [[i]],...)中的错误:找不到对象'day' 

reprex软件包(v0.3.0)创建于2020-05-27 sup>

i am trying to replace line-by-line scripting to produce ggplot2 graphics with functions - but have come unstuck with facet_wrap

To generalise the problem, I have created this toy dataset - which plots a value over time for two subjects ("IDs)

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)

With the following scripting approach, i can produce line plots of the value for the day - facetted on the two subjects

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

I then try to do this by creating and then calling a function using this code:

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

But I get the following error:

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

Interesting, if I hardcode "ID" into the function, everything works - and I don't even have to pass a faceting variables

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

But this sort of defeats the generalising benefit of creating a function

I would be grateful if someone could tell me what i am doing wrong and what might be the work-around

Thanks

PS. I have done a check for an answer on StackExchange, and although there are several somewhat similar questions about facet_wrap, either I could not get the suggested solutions to work, or else did not understand them

解决方案

Because non-standard evaluation changes the scoping rules in subtle ways, you cannot simply feed variables into aes() or vars() calls within functions (the ~ formula notation wraps vars()). A more detailed treatment of this problem you can find here: https://ggplot2.tidyverse.org/articles/ggplot2-in-packages.html

One of the solutions is to wrap you variable names into {{...}}, which signals that the non standard evaluation should occur with whatever expression is given as the argument, instead of the evaluated value of the argument expression.

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)

Created on 2020-05-27 by the reprex package (v0.3.0)

Also, note that you should also double bracket the x and y variables. The only reason that it worked before was because the day and value were variables in the global environment (and of the length nrow(df)). The following returns an error if run in a clean environment:

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

Created on 2020-05-27 by the reprex package (v0.3.0)

这篇关于ggplot2:将因子变量传递给facet_wrap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆