Como lidar com as notas da verificação CM R do "sem ligação visível para a variável global" quando minha sintaxe ggplot2 é sensata?

180

Edição: Hadley Wickham salienta que eu falhei errado. A verificação do CMD está lançando NOTAS, não avisos. Sinto muito pela confusão. Foi a minha supervisão.

A versão curta

R CMD checklança essa nota toda vez que uso a sintaxe de criação de plotagem sensível no ggplot2:

no visible binding for global variable [variable name]

Entendo por que o R CMD check faz isso, mas parece estar criminalizando toda uma veia de sintaxe sensível. Não tenho certeza de que medidas tomar para que meu pacote seja aprovado R CMD checke seja admitido no CRAN.

O fundo

Sascha Epskamp postou anteriormente sobre o mesmo problema . A diferença, eu acho, é que subset()a página de manual diz que foi projetada para uso interativo .

No meu caso, a questão ainda não acabou, subset()mas sobre um recurso principal de ggplot2: the data =argument.

Um exemplo de código que escrevo que gera essas notas

Aqui está uma subfunção no meu pacote que adiciona pontos a um gráfico:

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, ao analisar esse código, dirá

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

Por que a verificação R CMD está certa

A verificação está tecnicamente correta. x.valuesey.values

  • Não estão definidos localmente na função JitteredResponsesByContrast()
  • Não são predefinidos no formulário x.values <- [something]globalmente ou no chamador.

Em vez disso, são variáveis ​​dentro de um quadro de dados definido anteriormente e passado para a função JitteredResponsesByContrast().

Por que o ggplot2 dificulta apaziguar a verificação do R CMD

O ggplot2 parece incentivar o uso de um dataargumento. O argumento de dados, presumivelmente, é o motivo pelo qual esse código será executado

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

mas esse código produzirá um erro de objeto não encontrado:

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

Duas soluções alternativas e por que eu estou feliz com nenhuma das duas

A estratégia NULLing out

Matthew Dowle recomenda definir as variáveis ​​problemáticas como NULL primeiro, que no meu caso seriam assim:

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))
    )
  )
}

Aprecio esta solução, mas não gosto por três razões.

  1. não serve a nenhum propósito adicional além de apaziguador R CMD check.
  2. não reflete intenção. Isso aumenta a expectativa de que a aes()chamada veja nossas variáveis ​​agora NULL (não verá), enquanto obscurece o objetivo real (fazendo com que o R CMD verifique as variáveis ​​que aparentemente não saberia que estavam vinculadas)
  3. Os problemas de 1 e 2 se multiplicam porque toda vez que você escreve uma função que retorna um elemento de plotagem, é necessário adicionar uma instrução NULLing confusa

A estratégia with ()

Você pode usar with()para sinalizar explicitamente que as variáveis ​​em questão podem ser encontradas dentro de um ambiente maior. No meu caso, usar with()esta aparência:

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

Esta solução funciona. Mas não gosto dessa solução porque ela nem funciona da maneira que eu esperava. Se with()realmente estivesse resolvendo o problema de apontar o intérprete para onde estão as variáveis, eu nem precisaria do data =argumento. Mas, with()não funciona assim:

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

Então, novamente, acho que essa solução tem falhas semelhantes à estratégia NULLing:

  1. Eu ainda tenho que passar por todas as funções do elemento plot e envolver a lógica em uma with()chamada
  2. A with()ligação é enganosa. Eu ainda preciso fornecer um data =argumento; tudo o que with()está fazendo é apaziguador R CMD check.

Conclusão

Na minha opinião, há três opções que eu poderia tomar:

  1. Faça lobby no CRAN para ignorar as notas argumentando que elas são "falsas" (de acordo com a política do CRAN ) e faça isso toda vez que eu enviar um pacote
  2. Corrija meu código com uma das duas estratégias indesejáveis ​​(NULLing ou with()blocos)
  3. Zumbido muito alto e espero que o problema desapareça

Nenhum dos três me deixa feliz, e estou me perguntando o que as pessoas sugerem que eu (e outros desenvolvedores de pacotes que desejam explorar o ggplot2) devam fazer. Agradecemos antecipadamente a todos. Eu realmente aprecio a sua leitura mesmo através disso :-)

briandk
fonte
20
Eu gosto de # 1 e # 3.
Ben Bolker
8
@BenBolker, essas são minhas técnicas também.
25412 hadley
6
Existe uma quarta opção: modificar 'R CMD check' e enviar um patch para r-devel para consideração. Eu suspeito que você achará muito difícil (e possivelmente impossível) detectar quais são espúrias e quais não são. Se alguém inventou um pedaço de código para fazer isso, então ...
Matt Dowle
6
Outra estratégia é usaraes_string
Hadley
2
Este parece ser um problema com transforme subsettambém (não 100% de certeza, mas faz sentido).
BrodieG

Respostas:

45

Você já tentou com em aes_stringvez de aes? Isso deve funcionar, embora eu não tenha tentado:

aes_string(x = 'x.values', y = 'y.values')
Harlan
fonte
4
apenas um aviso: aeso while aes_stringnão define parâmetros posicionais xe y.
Topchef 18/10/2013
6
Apenas mais um aviso. aes_string não permite usar funções para manipular os valores xey. Digamos que você gostaria de registrar a transformação y; nesse caso, aes_string (x = 'x.values', y = 'log (y.values)') obviamente não funciona. Eu mesmo uso muito esse tipo de transformação, portanto aes_string nem sempre é uma opção para mim.
Dr. Mike
Talvez essa resposta (e a que aes_stringtiver mais votos) deva ser atualizada, pois a documentação diz: "Todas essas funções são reprovadas por software. Por favor, use expressões idiomáticas de avaliação (consulte a seção de quase-cotação na documentação de aes ())." (ggplot2 versão 3.2.1). Isso provavelmente é rlang::.datao melhor candidato para silenciar essas anotações.
Vandenman 04/11/19
86

Você tem duas soluções:

  • Reescreva seu código para evitar uma avaliação não padrão. Para ggplot2, isso significa usar em aes_string()vez de aes()(como descrito por Harlan)

  • Adicione uma chamada para globalVariables(c("x.values", "y.values"))algum lugar no nível superior do seu pacote.

Você deve se esforçar para obter 0 NOTAS no seu pacote ao enviar para o CRAN, mesmo se tiver que fazer algo ligeiramente hacky. Isso facilita a vida do CRAN e de você.

(Atualizado em 31/12/2014 para refletir meus pensamentos mais recentes sobre isso)

Hadley
fonte
26
globalVariablesé um truque hediondo e eu nunca vou usá-lo.
25412 hadley
10
Pelo que vale a pena, o envio do meu pacote foi rejeitado por causa dessas anotações e foi dito para usar a função utils :: globalVariables. Como não estou em posição de argumentar, foi o que fiz.
jbryer
9
Concordo que seria melhor ignorá-los, mas meu código usa muito ggplote data.table, e, portanto, toneladas de estas advertências, que me impediam de perceber outros avisos mais importantes que realmente eram problemas que eu precisava para correção.
Ken Williams
108
@hadley, você não deve dizer que nunca usará as coisas quando apenas dois anos depois achar que está tudo bem
Hadley
10
resolução de Ano Novo? Vou manter meus olhos abertos para ggplot::scale_dualAxis.sqrtgráficos de pizza 3D com padrões de preenchimento.
baptiste
29

Esta pergunta foi feita e respondida há um tempo, mas apenas para sua informação, desde a versão 2.1.0 existe outra maneira de contornar as notas:aes_(x=~x.values,y=~y.values).

stefan.schroedl
fonte
12

E se

getRversion() >= "3.1.0"

Você pode adicionar uma chamada no nível superior do pacote:

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

de:

help("suppressForeignCheck")
Bastiaan Quast
fonte
3
Essa é uma solução justa. Obrigado! Eu tinha considerado isso, mas o problema é que tenho muitas variáveis ​​como x.valuese y.values, portanto, teria que registrar TODAS.
Briandk
4
Isso não é o que suppressForeignChecké usado para
Hadley
10
Onde é realmente o nível superior ? Em qual arquivo eu adiciono este comando?
amigos estão dizendo sobre drmariod
9
Por costume, isso é colocado em um zzz.Rarquivo ./R/. Por exemplo, github.com/HughParsonage/grattan/blob/master/R/zzz.R
Hugh
6
@hadley, para que é usado? A ajuda ("suppressForeignCheck") parece indicar que é para um "símbolo nativo calculado em tempo de execução", mas que diabos é isso?
pdb 27/02
8

Em 2019, a melhor maneira de contornar isso é usar o .dataprefixo do rlangpacote. Isso diz ao R para tratar x.valuese y.valuescomo colunas em um data.frame(para não reclamar de variáveis ​​indefinidas).

Nota: Isso funciona melhor se você tiver nomes de colunas predefinidos que você sabe que existirão na entrada de dados

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

Adicione esta linha de código ao arquivo no qual você fornece a documentação no nível do pacote:

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

Exemplo aqui

stevec
fonte