Bagaimana saya bisa menangani R CMD memeriksa catatan "tidak terlihat mengikat untuk variabel global" ketika sintaks ggplot2 saya masuk akal?

180

EDIT: Hadley Wickham menunjukkan bahwa saya salah bicara. Pemeriksaan R CMD melempar CATATAN, bukan Peringatan. Saya sangat menyesal atas kebingungan ini. Itu pengawasan saya.

Versi singkat

R CMD checkmelempar catatan ini setiap kali saya menggunakan sintaks pembuatan-plot yang masuk akal di ggplot2:

no visible binding for global variable [variable name]

Saya mengerti mengapa pemeriksaan R CMD melakukan itu, tetapi tampaknya mengkriminalkan seluruh uraian sintaks yang masuk akal. Saya tidak yakin langkah apa yang harus diambil untuk mendapatkan paket saya untuk lulus R CMD checkdan diterima ke CRAN.

Latar belakang

Sascha Epskamp sebelumnya diposting pada dasarnya masalah yang sama . Perbedaannya, saya pikir, adalah bahwa subset()halaman manual mengatakan itu dirancang untuk penggunaan interaktif .

Dalam kasus saya, masalahnya belum selesai subset()tetapi lebih pada fitur inti ggplot2: data =argumen.

Contoh kode yang saya tulis yang menghasilkan catatan ini

Berikut adalah sub-fungsi dalam paket saya yang menambahkan poin ke plot:

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, pada penguraian kode ini, akan mengatakan

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

Mengapa pemeriksaan R CMD benar

Secara teknis pemeriksaannya benar. x.valuesdany.values

  • Tidak didefinisikan secara lokal dalam fungsi JitteredResponsesByContrast()
  • Tidak ditentukan sebelumnya dalam bentuk x.values <- [something]baik secara global maupun dalam penelepon.

Sebagai gantinya, mereka variabel dalam kerangka data yang didefinisikan sebelumnya dan diteruskan ke fungsi JitteredResponsesByContrast().

Mengapa ggplot2 membuatnya sulit untuk menenangkan pemeriksaan CMD R

ggplot2 tampaknya mendorong penggunaan dataargumen. Argumen data, mungkin, adalah alasan mengapa kode ini akan dieksekusi

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

tetapi kode ini akan menghasilkan kesalahan objek-tidak-ditemukan:

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

Dua solusi, dan mengapa saya tidak senang dengan keduanya

Strategi NULLing out

Matthew Dowle merekomendasikan pengaturan variabel bermasalah ke NULL terlebih dahulu, yang dalam kasus saya akan terlihat seperti ini:

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

Saya menghargai solusi ini, tetapi saya tidak menyukainya karena tiga alasan.

  1. tidak ada tujuan tambahan selain memenuhi tuntutan R CMD check.
  2. itu tidak mencerminkan niat. Ini menimbulkan harapan bahwa aes()panggilan akan melihat variabel sekarang-NULL kami (tidak akan), sementara mengaburkan tujuan sebenarnya (membuat R CMD memeriksa variabel yang tampaknya tidak akan diketahui terikat)
  3. Masalah 1 dan 2 berlipat ganda karena setiap kali Anda menulis fungsi yang mengembalikan elemen plot, Anda harus menambahkan pernyataan NULLing yang membingungkan

Strategi with ()

Anda dapat menggunakan with()untuk secara eksplisit memberi sinyal bahwa variabel yang dimaksud dapat ditemukan di dalam beberapa lingkungan yang lebih besar. Dalam kasus saya, menggunakan with()terlihat seperti ini:

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

Solusi ini berfungsi. Tapi, saya tidak suka solusi ini karena bahkan tidak berfungsi seperti yang saya harapkan. Jika with()benar-benar memecahkan masalah menunjuk juru ke tempat variabel, maka saya seharusnya tidak perlu yang data =argumen. Tetapi, with()tidak berfungsi seperti itu:

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

Jadi, sekali lagi, saya pikir solusi ini memiliki kelemahan yang mirip dengan strategi NULLing:

  1. Saya masih harus melalui setiap fungsi elemen plot dan membungkus logika dalam with()panggilan
  2. The with()panggilan menyesatkan. Saya masih perlu memberikan data =argumen; semua with()lakukan adalah memenuhi tuntutan R CMD check.

Kesimpulan

Cara saya melihatnya, ada tiga opsi yang bisa saya ambil:

  1. Lobi CRAN untuk mengabaikan catatan dengan alasan bahwa mereka "palsu" (sesuai dengan kebijakan CRAN ), dan lakukan itu setiap kali saya mengirimkan paket
  2. Perbaiki kode saya dengan salah satu dari dua strategi yang tidak diinginkan (NULLing atau with()blokir)
  3. Bersenandung sangat keras dan berharap masalah hilang

Tidak satu pun dari ketiganya yang membuat saya bahagia, dan saya bertanya-tanya apa yang orang sarankan saya (dan pengembang paket lain yang ingin memanfaatkan ggplot2) harus lakukan. Terima kasih untuk semuanya. Saya sangat menghargai Anda membaca ini :-)

briandk
sumber
20
Saya suka # 1 dan # 3.
Ben Bolker
8
@ BenBolker itu adalah teknik masuk saya juga.
Hadley
6
Ada opsi ke-4: modifikasi 'R CMD check' dan kirim tambalan ke r-devel untuk dipertimbangkan. Saya menduga Anda akan menemukan cukup sulit (dan mungkin tidak mungkin) untuk mendeteksi mana yang palsu dan mana yang tidak. Jika ada yang datang dengan sepotong kode untuk melakukan itu, maka ...
Matt Dowle
6
Strategi lain adalah menggunakanaes_string
hadley
2
Ini tampaknya menjadi masalah dengan transformdan subsetjuga (tidak 100% yakin, tetapi masuk akal).
BrodieG

Jawaban:

45

Apakah Anda mencoba dengan aes_stringbukan aes? Ini seharusnya bekerja, walaupun saya belum mencobanya:

aes_string(x = 'x.values', y = 'y.values')
Harlan
sumber
4
hanya peringatan: aestidak sementara aes_stringtidak mendefinisikan parameter posisi xdan y.
topchef
6
Hanya peringatan lain. aes_string tidak memungkinkan Anda menggunakan fungsi untuk memanipulasi nilai x dan y. Katakanlah Anda ingin mencatat transformasi y dalam hal ini aes_string (x = 'x.values', y = 'log (y.values)') tentu saja tidak berfungsi. Saya sering menggunakan transformasi semacam ini sehingga aes_string tidak selalu menjadi pilihan bagi saya.
Dr. Mike
Mungkin jawaban ini (dan yang memiliki suara terbanyak) harus diperbarui sejak dokumentasi aes_stringmengatakan: "Semua fungsi ini sudah tidak digunakan lagi. Silakan gunakan idiom evaluasi yang rapi (lihat bagian kuasiquotasi dalam dokumentasi aes ())." (ggplot2 versi 3.2.1). Itu mungkin membuat rlang::.datakandidat terbaik untuk membungkam catatan ini.
Vandenman
86

Anda memiliki dua solusi:

  • Tulis ulang kode Anda untuk menghindari evaluasi yang tidak standar. Untuk ggplot2, ini berarti menggunakan aes_string()alih-alih aes()(seperti dijelaskan oleh Harlan)

  • Tambahkan panggilan ke globalVariables(c("x.values", "y.values"))suatu tempat di tingkat atas paket Anda.

Anda harus berusaha untuk 0 CATATAN dalam paket Anda ketika mengirimkan ke CRAN, bahkan jika Anda harus melakukan sesuatu yang sedikit peretasan. Ini membuat hidup lebih mudah bagi CRAN, dan lebih mudah bagi Anda.

(Diperbarui 2014-12-31 untuk mencerminkan pemikiran terakhir saya tentang ini)

Hadley
sumber
26
globalVariablesadalah hack yang mengerikan dan saya tidak akan pernah menggunakannya.
Hadley
10
Untuk apa yang layak, pengiriman paket saya ditolak karena catatan ini dan disuruh menggunakan fungsi utils :: globalVariables. Karena saya tidak dalam posisi untuk berdebat, itulah yang saya lakukan.
jbryer
9
Saya setuju bahwa yang terbaik adalah mengabaikannya, tetapi kode saya menggunakan banyak ggplotdan data.table, dan dengan demikian memiliki banyak peringatan ini, yang membuat saya tidak memperhatikan peringatan lain yang lebih penting yang benar-benar masalah yang perlu saya perbaiki.
Ken Williams
108
@Hadley Anda tidak boleh mengatakan Anda tidak akan pernah menggunakan hal-hal ketika hanya dua tahun kemudian Anda berpikir itu baik
Hadley
10
resolusi tahun baru? Saya akan tetap membuka mata ggplot::scale_dualAxis.sqrtdan grafik pai 3D dengan pola isian.
baptiste
29

Pertanyaan ini telah ditanyakan dan dijawab beberapa waktu lalu tetapi hanya untuk informasi Anda, karena versi 2.1.0 ada cara lain untuk menyiasati catatan:aes_(x=~x.values,y=~y.values).

stefan.schroedl
sumber
12

Jika

getRversion() >= "3.1.0"

Anda dapat menambahkan panggilan di tingkat atas paket:

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

dari:

help("suppressForeignCheck")
Bastiaan Quast
sumber
3
Itu solusi yang adil. Terima kasih! Saya telah mempertimbangkan ini, tetapi masalahnya adalah saya memiliki banyak sekali variabel suka x.valuesdan y.values, jadi saya harus mendaftarkan SEMUA dari mereka.
briandk
4
Bukan suppressForeignCheckitu yang digunakan untuk
hadley
10
Di mana sebenarnya level teratas ? Di file mana saya harus menambahkan perintah ini?
drmariod
9
Secara khusus, ini dimasukkan ke dalam zzz.Rfile ./R/. Misalnya, github.com/HughParsonage/grattan/blob/master/R/zzz.R
Hugh
6
@ Madley, untuk apa ini digunakan? help ("suppressForeignCheck") tampaknya menyiratkan itu untuk "simbol asli yang dihitung run-time", tapi apa-apaan itu?
pdb
8

Pada 2019, cara terbaik untuk menyiasatinya adalah dengan menggunakan .dataawalan dari rlangpaket. Ini memberitahu R untuk memperlakukan x.valuesdan y.valuessebagai kolom dalam data.frame(sehingga tidak akan mengeluh tentang variabel yang tidak ditentukan).

Catatan: Ini berfungsi paling baik jika Anda memiliki nama kolom yang telah ditentukan sebelumnya yang Anda tahu akan ada di input data Anda

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

Tambahkan baris kode ini ke file di mana Anda memberikan dokumentasi tingkat paket:

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

Contoh di sini

stevec
sumber