Почему autoplot () с geom_point () не принимает переменную внутри функции [duplicate]

Посмотрите на Integer.java, если значение находится между -128 и 127, оно будет использовать кешированный пул, поэтому (Integer) 1 == (Integer) 1 пока (Integer) 222 != (Integer) 222

 /**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}       
45
задан Paul Hiemstra 18 May 2012 в 23:44
поделиться

6 ответов

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

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)
37
ответ дан baptiste 18 August 2018 в 01:59
поделиться
  • 1
    Возможно, это официальный (но недокументированный) способ, я думаю. – kohske 19 May 2012 в 08:24
  • 2
    если честно, я думаю, что это действительно должно быть дефолтом. То же самое с plyr, я всегда сильно запутываюсь, когда ** ply не находит переменную, которая найдет другие функции R с обычными правилами определения области видимости. – baptiste 19 May 2012 в 08:40
  • 3
    +1 - @kohske и @baptiste. Мне также нравится это лучше всего. Стоит отметить, однако, что он делает что-то другое, чем мое решение, что видно из: (1) удаления y=1:10 из data.frame xy; (2) помещение y<-1:10 в глобальную среду; и (3) поместить y<-10:1 в тело функции до вызова ggplot. По сути, мое решение позволяет передавать выбранные аргументы, не изменяя при этом других правил. Ваш полностью изменяет поведение области видимости ggplot() (вот почему мне это нравится). – Josh O'Brien 19 May 2012 в 17:06
  • 4
    @ JoshO'Brien да. Я также придерживаюсь правила, согласно которому аргументы aes () должны всегда поступать из data.frame, и в этом случае единственными объектами, которые я, возможно, захочу выбрать из окружающей среды, являются такие параметры, как YMu. – baptiste 19 May 2012 в 22:11
  • 5
    Это действительно прямолинейно, но я согласен с тем, что это должно быть значение по умолчанию. Я думал, что aes внутри ggplot работает как закрытие, сохраняя все использованные объекты со всех сторон; очевидно, это не так. Спасибо! – fabb 20 May 2012 в 09:04

Вы посмотрели на решение, данное @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
1
ответ дан BBrill 18 August 2018 в 01:59
поделиться
  • 1
    Это дубликат ответа @ baptiste, и IMO неоправданно использует другой пример, предоставленный OP при условии воспроизводимого примера. Я бы предложил удалить (и, возможно, прокомментировать баптист с проблемой Github, которую вы связали). – Max Ghenis 5 September 2015 в 18:05

Вот альтернатива, которая позволяет передавать любое значение через аргумент YMul, не добавляя его в файл ff.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)

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

substitute({ggplot(Data, aes(x=x, y=y*YMul))}, list(YMul=100))
10
ответ дан Josh O'Brien 18 August 2018 в 01:59
поделиться
  • 1
    +1 Спасибо! Я знал, что есть способ сделать это, но не нашел времени, чтобы разобраться с этим. Очень круто. – Justin 18 May 2012 в 22:03
  • 2
    @Justin - Рад, что это полезно. То, что I никогда не занимало время, чтобы разобраться, - это то, как работает предварительная оценка ggplot. В качестве примера я просто поместил оператор browser() внутри вызова aes(), а после ввода sys.frames() я получил список из 23 сред, ни один из которых (??), по-видимому, не дает прямого доступа к значению из YMul. Хм. – Josh O'Brien 18 May 2012 в 22:15
  • 3
    Да ... его путь вне меня. У меня был некоторый пользовательский код любезно предоставлен Кохске, который сломался с новым выпуском и совершенно непостижимым для меня! Когда-нибудь мне хотелось бы понять прото ... – Justin 18 May 2012 в 22:23
  • 4
    @Justin и Josh: Вот связанная дискуссия о github: github.com/hadley/ggplot2/issues/248 Кажется, что обсуждались, но не были реализованы. – jthetzel 18 May 2012 в 22:32
  • 5
    +1 То же самое с bquote: eval (bquote (ggplot (Data, aes (x = x, y = y *. (YMul))) + geom_line ())). – Wojciech Sobala 19 May 2012 в 04:34

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

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

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)
5
ответ дан jthetzel 18 August 2018 в 01:59
поделиться
  • 1
    YMul не обязательно должен быть частью data.frame. Он просто должен быть определен в области, где оценивается объект ggplot, который является глобальным, а не функцией. – Justin 18 May 2012 в 21:40
  • 2
    @ Джастин: Спасибо. Я этого не осознавал. Интересно, что ggplot(), похоже, сначала ищет YMul в кадре данных, а затем, если не найден в глобальной среде, очевидно, пропуская аргументы функции. Я не нашел никакой информации о том, как ggplot() ищет пространства имен, но опять же я не выглядел очень тяжело. – jthetzel 18 May 2012 в 22:04
  • 3
    Это, безусловно, более простой вариант запомнить и напечатать. Возможно, это не здорово, если ваш dataframe имеет миллиард строк, но удобен для других ситуаций. – PatrickT 22 October 2017 в 16:18

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

YMul <- 2

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

plotfunc(xy)
0
ответ дан Justin 18 August 2018 в 01:59
поделиться

Я использую 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

В приведенном выше варианте «захват локальной среды» не является решением, потому что 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
4
ответ дан Metamorphic 18 August 2018 в 01:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: