Làm cách nào tôi có thể xử lý R kiểm tra CMD không có ràng buộc có thể nhìn thấy đối với các ghi chú biến đổi toàn cầu khi cú pháp ggplot2 của tôi hợp lý?


180

EDIT: Hadley Wickham chỉ ra rằng tôi sai chính tả. R Kiểm tra CMD đang ném GHI CHÚ, không phải Cảnh báo. Tôi vô cùng xin lỗi vì sự nhầm lẫn. Đó là sự giám sát của tôi.

Phiên bản ngắn

R CMD checkném ghi chú này mỗi khi tôi sử dụng cú pháp tạo cốt truyện hợp lý trong ggplot2:

no visible binding for global variable [variable name]

Tôi hiểu lý do tại sao kiểm tra R CMD làm điều đó, nhưng dường như nó đang hình sự hóa toàn bộ tĩnh mạch của cú pháp hợp lý. Tôi không chắc chắn những bước cần thực hiện để vượt qua gói hàng của mình R CMD checkvà được nhận vào CRAN.

Bối cảnh

Sascha Epskamp trước đây được đăng trên cùng một vấn đề . Sự khác biệt, tôi nghĩ, đó subset()là trang chủ của nó nói rằng nó được thiết kế để sử dụng tương tác .

Trong trường hợp của tôi, vấn đề không phải là kết thúc subset()mà là một tính năng cốt lõi của ggplot2: data =đối số.

Một ví dụ về mã tôi viết tạo ra các ghi chú này

Đây là một chức năng phụ trong gói của tôi có thêm điểm vào một âm mưu:

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, về phân tích mã này, sẽ nói

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

Tại sao kiểm tra R CMD là đúng

Kiểm tra là đúng kỹ thuật. x.valuesy.values

  • Không được định nghĩa cục bộ trong hàm JitteredResponsesByContrast()
  • Không được xác định trước ở dạng x.values <- [something]toàn cầu hoặc trong người gọi.

Thay vào đó, chúng là các biến trong một khung dữ liệu được xác định trước đó và được truyền vào hàm JitteredResponsesByContrast().

Tại sao ggplot2 gây khó khăn cho việc xoa dịu kiểm tra R CMD

ggplot2 dường như khuyến khích việc sử dụng một datađối số. Đối số dữ liệu, có lẽ là lý do tại sao mã này sẽ thực thi

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

nhưng này mã sẽ tạo ra một lỗi đối tượng-not-found:

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

Hai công việc, và tại sao tôi không hạnh phúc

Chiến lược NULLing ra

Matthew Dowle khuyên bạn nên đặt các biến có vấn đề thành NULL trước, trong trường hợp của tôi sẽ như sau:

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

Tôi đánh giá cao giải pháp này, nhưng tôi không thích nó vì ba lý do.

  1. nó không phục vụ mục đích bổ sung ngoài việc xoa dịu R CMD check.
  2. nó không phản ánh ý định. Điều này đặt ra kỳ vọng rằng aes()cuộc gọi sẽ thấy các biến NULL hiện tại của chúng tôi (sẽ không), trong khi che khuất mục đích thực sự (làm cho R CMD kiểm tra nhận biết các biến mà dường như không biết là bị ràng buộc)
  3. Các vấn đề của 1 và 2 nhân lên vì mỗi khi bạn viết một hàm trả về một phần tử cốt truyện, bạn phải thêm một câu lệnh NULLing khó hiểu

Chiến lược với ()

Bạn có thể sử dụng with()để báo hiệu rõ ràng rằng các biến trong câu hỏi có thể được tìm thấy bên trong một số môi trường lớn hơn. Trong trường hợp của tôi, sử dụng with()trông như thế này:

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

Giải pháp này hoạt động. Nhưng, tôi không thích giải pháp này vì nó thậm chí không hoạt động theo cách tôi mong đợi. Nếu with()đã thực sự giải quyết vấn đề của chỉ người phiên dịch đến nơi mà các biến là, sau đó tôi thậm chí không nên cần những data =cuộc tranh cãi. Nhưng, with()không hoạt động theo cách đó:

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

Vì vậy, một lần nữa, tôi nghĩ giải pháp này có những sai sót tương tự với chiến lược NULLing:

  1. Tôi vẫn phải trải qua mọi chức năng của phần tử cốt truyện và gói logic trong một with()cuộc gọi
  2. Cuộc with()gọi là sai lệch. Tôi vẫn cần cung cấp một data =lập luận; tất cả with()đang làm là hấp dẫn R CMD check.

Phần kết luận

Theo cách tôi thấy, có ba lựa chọn tôi có thể thực hiện:

  1. Hành lang CRAN để bỏ qua các ghi chú bằng cách lập luận rằng chúng là "giả" (theo chính sách CRAN ) và làm điều đó mỗi khi tôi gửi gói
  2. Sửa mã của tôi bằng một trong hai chiến lược không mong muốn (NULLing hoặc with()khối)
  3. Hum thực sự lớn tiếng và hy vọng vấn đề biến mất

Không ai trong số ba người làm tôi hạnh phúc, và tôi tự hỏi mọi người đề nghị tôi (và các nhà phát triển gói khác muốn khai thác vào ggplot2) nên làm gì. Cảm ơn tất cả trước. Tôi thực sự đánh giá cao việc bạn thậm chí đọc qua điều này :-)


20
Tôi thích # 1 và # 3.
Ben Bolker

8
@BenBolker cũng là những kỹ thuật của tôi.
hadley

6
Có một tùy chọn thứ 4: sửa đổi 'R CMD check' và gửi một bản vá cho r-devel để xem xét. Tôi nghi ngờ bạn sẽ thấy khá khó khăn (và có thể là không thể) để phát hiện cái nào là giả và cái nào không. Nếu bất cứ ai nghĩ ra một đoạn mã để làm điều đó, thì ...
Matt Dowle

6
Một chiến lược khác là sử dụngaes_string
hadley

2
Đây có vẻ là một vấn đề với transformsubsetquá (không chắc chắn 100%, nhưng nó có ý nghĩa).
BrodieG

Câu trả lời:


45

Bạn đã thử với aes_stringthay vì aes? Điều này sẽ hoạt động, mặc dù tôi đã không thử nó:

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

4
chỉ là một cảnh báo: aeskhông trong khi aes_stringkhông xác định tham số vị trí xy.
topchef

6
Chỉ là một cảnh báo khác. aes_opes không cho phép bạn sử dụng các hàm để thao tác các giá trị x và y. Giả sử bạn muốn đăng nhập biến đổi y trong trường hợp aes_opes (x = 'x.values', y = 'log (y.values)') tất nhiên không hoạt động. Bản thân tôi sử dụng các loại biến đổi này rất nhiều vì vậy aes_opes không phải lúc nào cũng là một lựa chọn cho tôi.
Bác sĩ Mike

Có lẽ câu trả lời này (và câu trả lời có nhiều phiếu nhất) nên được cập nhật vì tài liệu có nội dung aes_string: "Tất cả các chức năng này đều không được chấp nhận. Thay vào đó, hãy sử dụng các thành ngữ đánh giá gọn gàng (xem phần khai báo trong tài liệu aes ())." (ggplot2 phiên bản 3.2.1). Điều đó có thể làm cho rlang::.dataứng cử viên tốt nhất để im lặng những ghi chú.
Vandenman

86

Bạn có hai giải pháp:

  • Viết lại mã của bạn để tránh đánh giá không chuẩn. Đối với ggplot2, điều này có nghĩa là sử dụng aes_string()thay vì aes()(như được mô tả bởi Harlan)

  • Thêm một cuộc gọi đến globalVariables(c("x.values", "y.values"))một nơi nào đó ở cấp cao nhất của gói của bạn.

Bạn nên cố gắng đạt 0 GHI CHÚ trong gói của mình khi gửi tới CRAN, ngay cả khi bạn phải làm điều gì đó hơi hack. Điều này làm cho cuộc sống dễ dàng hơn cho CRAN, và dễ dàng hơn cho bạn.

(Cập nhật 2014-12-31 để phản ánh những suy nghĩ mới nhất của tôi về điều này)


26
globalVariableslà một hack đáng ghét và tôi sẽ không bao giờ sử dụng nó.
hadley

10
Đối với những gì có giá trị, việc gửi gói của tôi đã bị từ chối vì những ghi chú này và được yêu cầu sử dụng chức năng utils :: globalVariables. Vì tôi không ở vị trí để tranh luận, đó là những gì tôi đã làm.
jbowder

9
Tôi đồng ý rằng nó sẽ là tốt nhất để bỏ qua chúng, nhưng sử dụng mã của tôi rất nhiều ggplotdata.table, và do đó có tấn của những cảnh báo này, mà đã giữ tôi khỏi nhận thấy các cảnh báo khác quan trọng hơn đó thực sự là vấn đề tôi cần phải sửa chữa.
Ken Williams

108
@hadley bạn không nên nói rằng bạn sẽ không bao giờ sử dụng mọi thứ khi chỉ hai năm sau bạn nghĩ nó ổn
hadley

10
Nghị quyết năm mới? Tôi sẽ để mắt mở ggplot::scale_dualAxis.sqrtvà biểu đồ hình tròn 3D với các mẫu điền.
baptiste

29

Câu hỏi này đã được hỏi và trả lời cách đây một thời gian nhưng chỉ với thông tin của bạn, vì phiên bản 2.1.0 có một cách khác để khắc phục các ghi chú:aes_(x=~x.values,y=~y.values).


12

Nếu

getRversion() >= "3.1.0"

Bạn có thể thêm một cuộc gọi ở cấp cao nhất của gói:

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

từ:

help("suppressForeignCheck")

3
Đó là một giải pháp công bằng. Cảm ơn! Tôi đã xem xét điều này, nhưng vấn đề là tôi có rất nhiều biến số x.valuesy.valuesvì vậy tôi phải đăng ký TẤT CẢ chúng.
briandk

4
Đó không phải là những gì suppressForeignCheckđược sử dụng cho
hadley

10
Trường hợp thực sự là cấp cao nhất ? Trong tập tin nào tôi thêm lệnh này?
drmariod

9
Theo tùy chỉnh, điều này được đặt trong một zzz.Rtập tin ./R/. Ví dụ: github.com/HughParsonage/grattan/blob/master/R/zzz.R
Hugh

6
@hadley, nó dùng để làm gì? help ("boosterForeignCheck") dường như ngụ ý nó là "biểu tượng gốc được tính thời gian chạy", nhưng cái quái gì vậy?
pdb

8

Năm 2019, cách tốt nhất để khắc phục điều này là sử dụng .datatiền tố từ rlanggói. Điều này bảo R xử lý x.valuesy.valuesnhư các cột trong một data.frame(vì vậy nó sẽ không phàn nàn về các biến không xác định).

Lưu ý: Điều này hoạt động tốt nhất nếu bạn có tên cột được xác định trước mà bạn biết sẽ tồn tại trong dữ liệu nhập của bạn

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

3

Thêm dòng mã này vào tệp mà bạn cung cấp tài liệu cấp gói:

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

Ví dụ ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.