Как я могу справиться с заметкой R CMD check "no visible binding for global variable", когда мой синтаксис ggplot2 является разумным?

EDIT: Hadley Wickham указывает, что я оговорился. R CMD check выдает NOTES, а не Warnings. Я ужасно извиняюсь за путаницу. Это был мой недосмотр.

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

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

no visible binding for global variable [variable name]

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

Предыстория

Саша Эпскамп ранее писал о по сути той же проблеме. Разница, я думаю, в том, что на manpage 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 check прав

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

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

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

Почему ggplot2 затрудняет проверку R CMD

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

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

но этот код выдаст ошибку object-not-found:

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

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

Стратегия NULLing out

Мэтью Доул рекомендует сначала установить проблемные переменные в 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() увидит наши теперь уже NULL-переменные (это не так), скрывая при этом истинную цель (заставить R CMD check узнать о переменных, о которых он, очевидно, иначе не знал бы, что они связаны)
  3. Проблемы 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:

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

Заключение

Как я это вижу, есть три варианта, которые я могу предпринять:

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

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

169
задан Community 23 May 2017 в 12:18
поделиться