Локальные переменные внутри aes

Я пытаюсь использовать локальную переменную в aes когда я рисую с ggplot. Это моя проблема сводилась к сути:

 xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data,YMul=2){ ggplot(Data,aes(x=x,y=y*YMul))+geom_line() } plotfunc(xy) 

Это приводит к следующей ошибке:

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

Кажется, я не могу использовать локальные переменные (или аргументы функции) в aes . Может быть, это происходит из-за того, что содержимое aes выполняется позже, когда локальная переменная выходит за пределы области видимости? Как я могу избежать этой проблемы (кроме использования локальной переменной внутри aes )?

Я бы захватил местную среду,

 xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data, YMul = 2){ .e <- environment() ggplot(Data, aes(x = x, y = y*YMul), environment = .e) + geom_line() } plotfunc(xy) 

Вот альтернатива, которая позволяет передавать любое значение через аргумент YMul не добавляя его в Data data.frame или в глобальную среду:

 plotfunc <- function(Data, YMul = 2){ eval(substitute( expr = { ggplot(Data,aes(x=x,y=y*YMul)) + geom_line() }, env = list(YMul=YMul))) } plotfunc(xy, YMul=100) 

Чтобы увидеть, как это работает, попробуйте следующую строку в отдельности:

 substitute({ggplot(Data, aes(x=x, y=y*YMul))}, list(YMul=100)) 

ggplot() ожидает, что YMul будет переменной в кадре данных. YMull этого попробуйте включить YMull :

Благодаря @Justin: ggplot() , похоже, YMul ищет YMul в кадре данных, а если не найден, то в глобальной среде. Мне нравится добавлять такие переменные в фрейм данных, как это следует, поскольку это имеет смысл для меня концептуально. Мне также не нужно беспокоиться об изменениях глобальных переменных, которые имеют неожиданные последствия для функций. Но все остальные ответы также верны. Итак, используйте то, что вам подходит.

 require("ggplot2") xy <- data.frame(x = 1:10, y = 1:10) xy <- cbind(xy, YMul = 2) ggplot(xy, aes(x = x, y = y * YMul)) + geom_line() 

Или, если вам нужна функция в вашем примере:

 plotfunc <- function(Data, YMul = 2) { ggplot(cbind(Data, YMul), aes(x = x, y = y * YMul)) + geom_line() } plotfunc(xy) 

Я использую ggplot2, и ваш пример, похоже, отлично работает с текущей версией.

Тем не менее, легко придумать варианты, которые все еще создают проблемы. Я сам был смущен подобным поведением, и именно так я нашел этот пост (верхний результат Google для «ggplot, как оценивать переменные при передаче»). Например, если мы переместим ggplot из plotfunc:

 xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data,YMul=2){ geom_line(aes(x=x,y=y*YMul)) } ggplot(xy)+plotfunc(xy) # Error in eval(expr, envir, enclos) : object 'YMul' not found , у xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data,YMul=2){ geom_line(aes(x=x,y=y*YMul)) } ggplot(xy)+plotfunc(xy) # Error in eval(expr, envir, enclos) : object 'YMul' not found 

В приведенном выше варианте «захват локальной среды» не является решением, потому что ggplot не вызывается из функции, и только ggplot имеет аргумент «environment =».

Но теперь существует множество функций «aes_», «aes_string», «aes_q», которые похожи на «aes», но фиксируют локальные переменные. Если мы используем «aes_» в приведенном выше, мы все равно получаем ошибку, потому что теперь он не знает о «x». Но легко обращаться к данным напрямую, что решает проблему:

 plotfunc <- function(Data,YMul=2){ geom_line(aes_(x=Data$x,y=Data$y*YMul)) } ggplot(xy)+plotfunc(xy) # works , у plotfunc <- function(Data,YMul=2){ geom_line(aes_(x=Data$x,y=Data$y*YMul)) } ggplot(xy)+plotfunc(xy) # works 

Вы посмотрели на решение, данное @wch (W. Chang)?

https://github.com/hadley/ggplot2/issues/743

Я думаю, что это лучший

по существу, похож на @baptiste, но включает ссылку на среду непосредственно в вызове ggplot

Я сообщаю об этом здесь

 g <- function() { foo3 <- 4 ggplot(mtcars, aes(x = wt + foo3, y = mpg), environment = environment()) + geom_point() } g() # Works 

Если вы выполняете свой код вне функции, он работает. И если вы выполняете код внутри функции с YMul определенным глобально, он работает. Я не совсем понимаю внутреннюю работу ggplot но это работает …

 YMul <- 2 plotfunc <- function(Data){ ggplot(Data,aes(x=x,y=y*YMul))+geom_line() } plotfunc(xy) 
  • значение ошибки ddply: атрибут 'names' должен быть такой же длины, как и вектор
  • Разделить разделенные запятыми строки в столбце на отдельные строки
  • Удалите 'a' из легенды при использовании эстетики и geom_text
  • Настроить тики x-axis
  • Толщина границы контрольной точки в ggplot
  • Как создать индикатор выполнения при использовании функции «foreach ()» в R?
  • Создание произвольных окон в ggplot2
  • Как удалить столбцы, содержащие ТОЛЬКО НС?
  • Подмножество по группам с data.table
  • R строк строки сценария при ошибке?
  • Заменить бары в geom_bar ggplot2
  • Давайте будем гением компьютера.