ggplot2: передать переменную фактора в facet_wrap - PullRequest
0 голосов
/ 27 мая 2020

Я пытаюсь заменить построчный скрипт для создания графики ggplot2 с функциями, но у меня возникли проблемы с facet_wrap

Чтобы обобщить проблему, я создал этот набор данных игрушек, который отображает значение над время для двух субъектов («идентификаторы»)

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) 

I затем попробуйте сделать это, создав и затем вызвав функцию, используя этот код:

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, либо я не смог заставить предложенные решения работать, либо не понял их

1 Ответ

1 голос
/ 27 мая 2020

Поскольку нестандартная оценка изменяет правила области видимости незаметным образом, вы не можете просто передать переменные в вызовы 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)

Создано 27 мая 2020 г. пакет репекс (v0.3.0)

Также обратите внимание, что вы также должны заключить в двойные скобки переменные x и y. Единственная причина, по которой это работало раньше, заключалась в том, что day и value были переменными в глобальной среде (и имели длину 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

Создано 27.05.2020 с помощью пакета реплекс (v0.3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...