ฉันจะจัดการการตรวจสอบ R CMD ได้อย่างไร“ ไม่มีการเชื่อมที่มองเห็นได้สำหรับตัวแปรส่วนกลาง” บันทึกเมื่อไวยากรณ์ ggplot2 ของฉันสมเหตุสมผล


180

แก้ไข: Hadley Wickham ชี้ให้เห็นว่าฉัน misspoke การตรวจสอบ CMD กำลังขว้างไปที่บันทึกไม่ใช่คำเตือน ฉันเสียใจอย่างมากสำหรับความสับสน มันเป็นการกำกับดูแลของฉัน

รุ่นสั้น ๆ

R CMD checkโยนบันทึกนี้ทุกครั้งที่ฉันใช้ไวยากรณ์การสร้างพล็อตที่สมเหตุสมผลใน ggplot2:

no visible binding for global variable [variable name]

ฉันเข้าใจว่าเหตุใดการตรวจสอบของ CM CM จึงเป็นเช่นนั้น แต่ดูเหมือนว่าจะทำให้เกิดความผิดทางอาญาทั้งเส้นเลือดของไวยากรณ์ที่มีเหตุผลอย่างอื่น ฉันไม่แน่ใจว่าต้องดำเนินการอย่างไรเพื่อให้พัสดุของฉันผ่านR CMD checkและเข้ารับการตรวจ CRAN

พื้นหลัง

Sascha Epskamp ก่อนหน้านี้โพสต์บนหลักปัญหาเดียวกัน ความแตกต่างที่ผมคิดว่าเป็นที่subset()manpage 's บอกว่ามันได้รับการออกแบบสำหรับการใช้งานแบบโต้ตอบ

ในกรณีของฉันปัญหาไม่ได้จบไป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]ทั้งแบบโกลบอลหรือในผู้โทร

แต่พวกเขากำลังตัวแปรภายใน dataframe JitteredResponsesByContrast()ที่ได้รับการกำหนดไว้ก่อนหน้านี้และผ่านเข้าสู่ฟังก์ชั่น

ทำไม ggplot2 ทำให้ยากต่อการเอาใจเช็ค R CMD

ggplot2 ดูเหมือนว่าจะสนับสนุนการใช้dataอาร์กิวเมนต์ อาร์กิวเมนต์ data สันนิษฐานว่าเป็นสาเหตุที่รหัสนี้จะทำงาน

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

แต่รหัสนี้จะสร้างข้อผิดพลาดที่ไม่พบวัตถุ:

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

สองรอบการทำงานและทำไมฉันมีความสุขกับทั้ง

กลยุทธ์ที่เป็นโมฆะ

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

ฉันขอขอบคุณวิธีแก้ปัญหานี้ แต่ฉันไม่ชอบด้วยเหตุผลสามประการ

  1. R CMD checkมันจะทำหน้าที่ไม่มีวัตถุประสงค์เพิ่มเติมนอกเหนือสยบ
  2. มันไม่สะท้อนความตั้งใจ มันเพิ่มความคาดหวังว่าการaes()โทรจะเห็นตัวแปร now-NULL ของเรา (จะไม่) ในขณะที่ปิดบังวัตถุประสงค์ที่แท้จริง (ทำให้ R CMD ตรวจสอบการรับรู้ถึงตัวแปรที่เห็นได้ชัดว่าไม่ทราบว่าถูกผูกไว้)
  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. Lobby CRAN เพื่อเพิกเฉยต่อบันทึกย่อโดยอ้างว่าพวกเขา "ปลอมแปลง" (ตามนโยบาย CRAN ) และทำเช่นนั้นทุกครั้งที่ฉันส่งแพคเกจ
  2. แก้ไขรหัสของฉันด้วยหนึ่งในสองกลยุทธ์ที่ไม่พึงประสงค์ (NULLing หรือwith()บล็อก)
  3. ครวญครางดังมากและหวังว่าปัญหาจะหายไป

ไม่มีสามคนที่ทำให้ฉันมีความสุขและฉันสงสัยว่าผู้คนแนะนำฉันอย่างไร (และผู้พัฒนาแพ็คเกจอื่น ๆ ที่ต้องการแตะ ggplot2) ควรทำ ขอบคุณทุกคนล่วงหน้า ฉันขอขอบคุณที่คุณอ่านข้อความนี้ :-)


20
ฉันชอบ # 1 และ # 3
Ben Bolker

8
@BenBolker เหล่านั้นก็เป็นเทคนิคการใช้งานด้วยเช่นกัน
hadley

6
มีตัวเลือกที่ 4 คือแก้ไข 'R CMD check' และส่ง patch เพื่อ r-devel เพื่อพิจารณา ฉันสงสัยว่าคุณจะพบว่ามันค่อนข้างยาก (และอาจเป็นไปไม่ได้) ในการตรวจสอบว่ามีการปลอมและที่ไม่ ถ้าใครขึ้นมาพร้อมกับชิ้นส่วนของรหัสที่จะทำอย่างนั้นแล้ว ...
แมตต์ Dowle

6
อีกกลยุทธ์คือการใช้aes_string
hadley

2
ดูเหมือนว่าจะมีปัญหากับtransformและsubsetเกินไป (ไม่แน่ใจ 100% แต่มันสมเหตุสมผล)
BrodieG

คำตอบ:


45

คุณได้ลองกับaes_stringแทนaes? สิ่งนี้จะใช้ได้แม้ว่าฉันจะไม่ได้ลอง:

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

4
เพียงแค่คำเตือน: aesไม่ในขณะที่ยังaes_stringไม่ได้กำหนดพารามิเตอร์ตำแหน่งและx y
topchef

6
เตือนอีกครั้ง aes_string ไม่อนุญาตให้คุณใช้ฟังก์ชันเพื่อจัดการค่า x และ y สมมติว่าคุณต้องการบันทึกการแปลง y ซึ่งในกรณีนี้ aes_string (x = 'x.values', y = 'log (y.values)') แน่นอนไม่ทำงาน ฉันใช้การแปลงแบบนี้เป็นจำนวนมากดังนั้น aes_string จึงไม่ใช่ตัวเลือกสำหรับฉันเสมอไป
ดร. ไมค์

บางทีคำตอบนี้ (และคำตอบที่ได้คะแนนมากที่สุด) ควรได้รับการอัปเดตเนื่องจากเอกสารของaes_stringsays: "ฟังก์ชั่นเหล่านี้ไม่ได้คัดค้านกรุณาใช้สำนวนการประเมินที่เป็นระเบียบแทน (ดูหัวข้อ quasiquotation ใน aes () (ggplot2 เวอร์ชั่น 3.2.1) นั่นอาจทำให้rlang::.dataผู้สมัครที่ดีที่สุดในการปิดเสียงโน้ตเหล่านี้
Vandenman

86

คุณมีสองวิธี:

  • เขียนโค้ดของคุณใหม่เพื่อหลีกเลี่ยงการประเมินที่ไม่ได้มาตรฐาน สำหรับ ggplot2 หมายถึงการใช้aes_string()แทนaes()(ตามที่อธิบายโดย Harlan)

  • เพิ่มการโทรไปglobalVariables(c("x.values", "y.values"))ที่ไหนสักแห่งในแพ็คเกจระดับบนสุดของคุณ

คุณควรพยายาม 0 บันทึกในแพ็คเกจของคุณเมื่อส่งถึง CRAN แม้ว่าคุณจะต้องทำอะไรที่แฮ็คเล็กน้อย สิ่งนี้ทำให้ชีวิตของ CRAN ง่ายขึ้นและง่ายขึ้นสำหรับคุณ

(อัปเดต 2014-12-31 เพื่อสะท้อนความคิดล่าสุดของฉันในเรื่องนี้)


26
globalVariablesเป็นแฮ็คที่น่ากลัวและฉันจะไม่ใช้มันเลย
hadley

10
สำหรับสิ่งที่คุ้มค่าการส่งแพ็กเกจของฉันถูกปฏิเสธเนื่องจากบันทึกเหล่านี้และได้รับคำสั่งให้ใช้ฟังก์ชัน utils :: globalVariables เนื่องจากฉันไม่สามารถโต้เถียงได้นั่นคือสิ่งที่ฉันทำ
jbryer

9
ผมยอมรับว่ามันจะดีที่สุดที่จะไม่สนใจพวกเขา แต่รหัสของฉันใช้จำนวนมากggplotและdata.tableและทำให้มีตันของคำเตือนเหล่านี้ซึ่งได้เก็บไว้ฉันจากการสังเกตเห็นคำเตือนที่สำคัญอื่น ๆ ที่จริงปัญหาฉันต้องการที่จะแก้ไข
Ken Williams

108
@hadley คุณไม่ควรจะพูดว่าคุณจะไม่ใช้สิ่งที่เมื่อเพียงสองปีต่อมาคุณคิดว่ามันของดี
ฮัดลีย์

10
ความละเอียดปีใหม่? ฉันจะเปิดตาของฉันggplot::scale_dualAxis.sqrtและแผนภูมิวงกลมสามมิติด้วยลวดลายเติม
baptiste

29

คำถามนี้ถูกถามและตอบในขณะที่ผ่านมา แต่สำหรับข้อมูลของคุณเนื่องจากเวอร์ชัน 2.1.0มีวิธีอื่นในการแก้ไขบันทึกย่อ:aes_(x=~x.values,y=~y.values).


12

ถ้า

getRversion() >= "3.1.0"

คุณสามารถเพิ่มสายที่ระดับบนสุดของแพ็คเกจ:

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

จาก:

help("suppressForeignCheck")

3
นั่นเป็นทางออกที่ยุติธรรม ขอบคุณ! ฉันพิจารณาเรื่องนี้แล้ว แต่ปัญหาคือฉันมีตัวแปรมากมายเช่นนี้x.valuesและy.valuesดังนั้นฉันต้องลงทะเบียนทั้งหมดของพวกเขา
briandk

4
นั่นไม่ใช่สิ่งที่suppressForeignCheckใช้สำหรับ
hadley

10
ที่จริงแล้วระดับสูงสุดอยู่ที่ไหน ฉันจะเพิ่มคำสั่งนี้ในไฟล์ใด
drmariod

9
โดยกำหนดเองนี้จะใส่ในแฟ้มในzzz.R ./R/ตัวอย่างเช่นgithub.com/HughParsonage/grattan/blob/master/R/zzz.R
Hugh

6
@hadley มันใช้ทำอะไร? ช่วย ("suppressForeignCheck") ดูเหมือนจะบอกเป็นนัยสำหรับ "สัญลักษณ์พื้นเมืองที่คำนวณโดยใช้เวลา" แต่สิ่งที่ heck คืออะไร
pdb

8

ในปี 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))
}

3

เพิ่มบรรทัดของรหัสนี้ลงในไฟล์ที่คุณให้เอกสารระดับแพ็คเกจ:

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

ตัวอย่างที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.