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

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

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

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

no visible binding for global variable [variable name]

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

Фон

Sascha Epskamp ранее размещался на по существу той же самой проблемой. Разница, я думаю, в том, что subset() manpage говорит, что она предназначена для интерактивного использования.

В моем случае проблема не превышает 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 затрудняет утилизацию проверки R CMD

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

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

но этот код вызовет ошибку, не найденную объектом:

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

Два обхода, и почему я не доволен ни

Стратегия NULLing out

Matthew Dowle рекомендует сначала установить проблемные переменные в 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))
    )
  )
}

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

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

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

Вы можете использовать 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:

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

Заключение

Как я вижу, есть три варианта:

  • Лобби CRAN игнорируют записи, утверждая, что они "ложные" (в соответствии с политика CRAN), и делайте это каждый раз, когда я отправить пакет
  • Исправьте мой код одной из двух нежелательных стратегий (блоки NULLing или with())
  • Хум действительно громко и надеюсь, что проблема исчезнет.

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

Ответ 1

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

aes_string(x = 'x.values', y = 'y.values')

Ответ 2

У вас есть два решения:

  • Перепишите код, чтобы избежать нестандартной оценки. Для ggplot2 это означает использование aes_string() вместо aes() (как описано Harlan)

  • Добавьте вызов globalVariables(c("x.values", "y.values")) где-нибудь на верхнем уровне вашего пакета.

Вы должны стремиться к 0 ПРИМЕЧАНИЯм в вашем пакете при отправке в CRAN, даже если вам нужно сделать что-то немного взломанное. Это облегчает жизнь CRAN и облегчает вам работу.

(Обновлено 2014-12-31, чтобы отразить мои последние мысли об этом)

Ответ 3

Этот вопрос был задан и получен ответ некоторое время назад, но только для вашего сведения, так как версия 2.1.0 есть еще один способ обойти заметки: aes_(x=~x.values,y=~y.values).

Ответ 4

Если

getRversion() >= "3.1.0"

Вы можете добавить вызов на верхний уровень пакета:

utils::suppressForeignCheck(c("x.values", "y.values"))

от

help("suppressForeignCheck")

Ответ 5

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

if(getRversion() >= "2.15.1")  utils::globalVariables(c("."))

Пример здесь

Ответ 6

В 2019 году лучший способ обойти это - использовать префикс .data из пакета rlang. Это говорит R обрабатывать x.values и y.values как столбцы в data.frame (поэтому он не будет жаловаться на неопределенные переменные).

Примечание. Это работает лучше всего, если у вас есть предопределенные имена столбцов, которые, как вы знаете, будут присутствовать при вводе данных

#' @importFrom rlang .data
my_func <- function(data) {
    ggplot(data, aes(x = .data$x, y = .data$y))
}