Как я могу обработать примечания проверки CMD «нет видимой привязки для глобальной переменной», когда мой синтаксис ggplot2 является разумным?

180

РЕДАКТИРОВАТЬ: Хэдли Уикхэм указывает, что я оговорился. R CMD проверяет выбрасывание NOTES, а не предупреждений. Мне ужасно жаль за путаницу. Это был мой недосмотр.

Короткая версия

R CMD checkвыдает эту заметку каждый раз, когда я использую разумный синтаксис создания графика в ggplot2:

no visible binding for global variable [variable name]

Я понимаю, почему проверка R CMD делает это, но, похоже, криминализирует всю вину разумного синтаксиса. Я не уверен, какие шаги предпринять, чтобы мой пакет прошел R CMD checkи был принят в CRAN.

Фон

Саша Эпскамп ранее публиковал по сути ту же проблему . Разница, я думаю, в том, что subset()на этой странице руководства написано, что она предназначена для интерактивного использования .

В моем случае, этот вопрос еще не закончен , subset()но по основной особенности ggplot2: в data =аргументе.

Пример кода, который я пишу, который генерирует эти заметки

Вот подфункция в моем пакете, которая добавляет точки на график:

JitteredResponsesByContrast <- function (data) {
  return(
    geom_point(
             aes(
               x = x.values, 
               y = y.values
             ),
             data     = data,
             position = position_jitter(height = 0, width = GetDegreeOfJitter(jj))
    )
  )
}

R CMD check, при разборе этого кода скажет

granovagg.contr : JitteredResponsesByContrast: no visible binding for
  global variable 'x.values'
granovagg.contr : JitteredResponsesByContrast: no visible binding for
  global variable 'y.values'

Почему R CMD проверка верна

Проверка технически верна. x.valuesиy.values

  • Не определены локально в функции JitteredResponsesByContrast()
  • Не определены заранее в форме x.values <- [something]ни глобально, ни в вызывающей стороне.

Вместо этого они являются переменными внутри фрейма данных, который определяется ранее и передается в функцию JitteredResponsesByContrast().

Почему ggplot2 мешает успокоить проверку CMD

ggplot2, кажется, поощряет использование dataаргумента. Предположительно, именно поэтому аргумент data будет выполнять этот код

library(ggplot2)
p <- ggplot(aes(x = hwy, y = cty), data = mpg)
p + geom_point()

но этот код выдаст ошибку «объект не найден»:

library(ggplot2)
hwy # a variable in the mpg dataset

Два обходных пути, и почему я счастлив ни тем, ни другим

Стратегия обнуления

Мэтью Доул рекомендует сначала установить для проблемных переменных значение NULL, что в моем случае будет выглядеть так:

JitteredResponsesByContrast <- function (data) {
  x.values <- y.values <- NULL # Setting the variables to NULL first
  return(
    geom_point(
             aes(
               x = x.values, 
               y = y.values
             ),
             data     = data,
             position = position_jitter(height = 0, width = GetDegreeOfJitter(jj))
    )
  )
}

Я ценю это решение, но мне не нравится его по трем причинам.

  1. это не служит никакой дополнительной цели, кроме умиротворения R CMD check.
  2. это не отражает намерения. Это повышает ожидание того, что aes()вызов увидит наши переменные now-NULL (это не будет), в то же время скрывая реальную цель (делая проверку CMD R осведомленной о переменных, которые, по-видимому, иначе бы не знали, были связаны)
  3. Проблемы 1 и 2 умножаются, потому что каждый раз, когда вы пишете функцию, которая возвращает элемент сюжета, вы должны добавить непонятный оператор NULLing

Стратегия с ()

Вы можете with()явно указать, что рассматриваемые переменные могут быть найдены в более крупной среде. В моем случае использование with()выглядит так:

JitteredResponsesByContrast <- function (data) {
  with(data, {
      geom_point(
               aes(
                 x = x.values, 
                 y = y.values
               ),
               data     = data,
               position = position_jitter(height = 0, width = GetDegreeOfJitter(jj))
      )
    }
  )
}

Это решение работает. Но мне не нравится это решение, потому что оно даже не работает так, как я ожидал. Если with()действительно решение проблемы указывает интерпретатору , где переменные, то я даже не нужно в data =аргумент. Но with()так не работает:

library(ggplot2)
p <- ggplot()
p <- p + with(mpg, geom_point(aes(x = hwy, y = cty)))
p # will generate an error saying `hwy` is not found

Итак, еще раз, я думаю, что это решение имеет недостатки, подобные стратегии NULLing:

  1. Мне все еще нужно пройти через каждую функцию элемента plot и обернуть логику в with()вызов
  2. with()Вызов в заблуждение. Мне все еще нужно предоставить data =аргумент; все with()это делает это умиротворение R CMD check.

Вывод

На мой взгляд, есть три варианта:

  1. Побуждайте CRAN игнорировать заметки, утверждая, что они «ложные» (согласно политике CRAN ), и делайте это каждый раз, когда я отправляю пакет
  2. Исправьте мой код с помощью одной из двух нежелательных стратегий (NULLing или with()блоков)
  3. Гул очень громко и надеюсь, что проблема уходит

Ни один из трех не делает меня счастливым, и мне интересно, что люди предлагают мне (и другим разработчикам пакетов, желающим подключиться к ggplot2). Спасибо всем заранее. Я очень ценю, что вы даже читаете это :-)

briandk
источник
20
Мне нравятся № 1 и № 3.
Бен Болкер
8
@BenBolker - это тоже мои приемы.
Хэдли
6
Существует 4-й вариант: измените 'R CMD check' и отправьте патч на r-devel для рассмотрения. Я подозреваю, что вы обнаружите, что довольно сложно (и, возможно, невозможно) обнаружить, какие из них являются ложными, а какие нет. Если кто-то придумал кусок кода, чтобы сделать это, тогда ...
Мэтт Доул
6
Другая стратегия заключается в использованииaes_string
хадли
2
Это , как представляется, проблема с transformи subsetтоже (не уверен на 100%, но это имеет смысл).
BrodieG

Ответы:

45

Вы пробовали с aes_stringвместо aes? Это должно работать, хотя я не пробовал:

aes_string(x = 'x.values', y = 'y.values')
Харлан
источник
4
просто предупреждение: aesделает, пока aes_stringне определяет позиционные параметры xи y.
topchef
6
Еще одно предупреждение. aes_string не позволяет вам использовать функции для манипулирования значениями x и y. Предположим, вы хотите записать в журнал преобразование y, и в этом случае aes_string (x = 'x.values', y = 'log (y.values)'), конечно, не работает. Я сам часто использую такого рода преобразования, поэтому aes_string не всегда подходит для меня.
Доктор Майк
Возможно, этот ответ (и тот, который набрал наибольшее количество голосов) следует обновить, поскольку документация aes_stringгласит: «Все эти функции мягко осуждаются. Вместо этого, пожалуйста, используйте аккуратные идиомы оценки (см. Раздел квазиквотации в документации по aes ())». (ggplot2 версия 3.2.1). Это, вероятно, делает rlang::.dataлучшим кандидатом, чтобы заставить замолчать эти заметки.
Ванденман