ความแตกต่างระหว่าง require () และ library () คืออะไร?


565

ความแตกต่างระหว่างrequire()และlibrary()คืออะไร?



7
การเพิ่มลิงค์ไปยังโพสต์บล็อกของ @ Yihui ยกเว้นว่าเขาต้องการโพสต์เวอร์ชันเป็นคำตอบ yihui.name/en/2014/07/library-vs-require
MichaelChirico

4
สรุปโพสต์บล็อกของ @ Yihui: "ท่านสุภาพบุรุษและสุภาพสตรีฉันเคยพูดเรื่องนี้มาแล้ว: ต้องการ () เป็นวิธีที่ผิดในการโหลดแพ็คเกจ R ใช้
De Novo

1
@DanHall ... เพราะlibrary()ล้มเหลวทันทีเสียงดังต้นและข้อความแสดงข้อผิดพลาดที่เกี่ยวข้อง (ถ้าไม่ได้ติดตั้งแพคเกจหรือไม่สามารถโหลดได้) ในขณะที่require()ไม่เกิดข้อผิดพลาดเพียงส่งคืนบูลีน FALSE ที่เงียบหายไป และทำให้รหัสล้มเหลวในภายหลังและเข้ารหัสลับมากขึ้นด้วยError: object “bar” not foundบน (พูด) บรรทัด 175
smci

1
@KonradRudolph: เสร็จแล้ว! ขอบคุณสำหรับความคิดเห็นของคุณ.
Marco

คำตอบ:


86

นอกจากคำแนะนำที่ดีที่ได้รับฉันจะเพิ่มสิ่งนี้:

อาจเป็นการดีที่สุดที่จะหลีกเลี่ยงการใช้require() เว้นแต่ว่าคุณจะใช้ค่าที่ส่งคืนเช่นในการตรวจสอบข้อผิดพลาดบางอย่างเช่นที่กำหนดโดย thierry

ในกรณีอื่น ๆ ส่วนใหญ่จะเป็นการดีกว่าที่จะใช้library()เพราะสิ่งนี้จะให้ข้อความแสดงข้อผิดพลาดเมื่อเวลาโหลดของบรรจุภัณฑ์หากไม่สามารถใช้งานแพ็คเกจได้ require()จะล้มเหลวโดยไม่มีข้อผิดพลาดหากแพ็คเกจไม่อยู่ที่นั่น นี่เป็นเวลาที่ดีที่สุดในการตรวจสอบว่าจำเป็นต้องติดตั้งแพ็คเกจหรือไม่ (หรืออาจไม่มีอยู่จริงเพราะมันสะกดผิด) การรับคำติชมข้อผิดพลาดก่อนและในเวลาที่เกี่ยวข้องจะหลีกเลี่ยงอาการปวดหัวที่อาจเกิดขึ้นได้ด้วยการติดตามว่าทำไมโค้ดในภายหลังล้มเหลวเมื่อพยายามใช้รูทีนไลบรารี


356

มีไม่มากในงานประจำวัน

อย่างไรก็ตามตามเอกสารสำหรับฟังก์ชั่นทั้งสอง (เข้าถึงได้โดยใส่?ก่อนชื่อฟังก์ชั่นและกดปุ่ม Enter) requireจะใช้ภายในฟังก์ชั่นเพราะมันออกคำเตือนและดำเนินการต่อหากไม่พบแพคเกจในขณะที่libraryจะโยนข้อผิดพลาด


1
#richiemorrisroe: ขอบคุณ มันหมายความว่าถ้าฉันโหลดแพ็คเกจที่ฉันต้องการที่จุดเริ่มต้นของรหัส R ของฉันมันไม่สำคัญว่าอันไหนที่ฉันเลือก
Marco

6
ตราบใดที่คุณไม่ได้โหลดแพ็กเกจไว้ในฟังก์ชั่น ฉันโหลดแพคเกจทั้งหมดของฉันโดยใช้ความต้องการและไม่ทราบว่าความแตกต่างคืออะไรจนกระทั่งฉันอ่านความช่วยเหลือหลังจากเห็นคำถามของคุณ
richiemorrisroe

45
อีกเหตุผลหนึ่งที่ฉันใช้requireคือมันทำให้ฉันไม่สามารถอ้างถึงแพ็กเกจได้เพราะlibrariesการฝึกฝนที่ทำให้ R-cognoscenti ขึ้นไปบนกำแพง นี่libraryคือตำแหน่งไดเร็กทอรีที่แพ็กเกจนั่งอยู่
IRTFM

22
พวกเขามีความแตกต่างที่เกี่ยวข้องมาก อย่าใช้require, เว้นแต่คุณตรวจสอบค่าตอบแทน (และในกรณีที่มักจะมีทางเลือกที่ดีกว่าเช่นloadNamespace)
Konrad Rudolph

256

ข้อดีอีกอย่างของrequire()มันคือมันส่งกลับค่าตรรกะโดยค่าเริ่มต้น TRUEหากมีการโหลดแพคเกจFALSEถ้าไม่ได้

> test <- library("abc")
Error in library("abc") : there is no package called 'abc'
> test
Error: object 'test' not found
> test <- require("abc")
Loading required package: abc
Warning message:
In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
  there is no package called 'abc'
> test
[1] FALSE

ดังนั้นคุณสามารถใช้require()ในสิ่งปลูกสร้างเช่นเดียวกับด้านล่าง ซึ่งส่วนใหญ่มีประโยชน์ถ้าคุณต้องการแจกจ่ายรหัสของคุณไปยังการติดตั้ง R ของเราแพคเกจอาจไม่ได้รับการติดตั้ง

if(require("lme4")){
    print("lme4 is loaded correctly")
} else {
    print("trying to install lme4")
    install.packages("lme4")
    if(require(lme4)){
        print("lme4 installed and loaded")
    } else {
        stop("could not install lme4")
    }
}

65

คุณสามารถใช้require()หากคุณต้องการติดตั้งแพ็กเกจหากจำเป็นเท่านั้นเช่น:

if (!require(package, character.only=T, quietly=T)) {
    install.packages(package)
    library(package, character.only=T)
}

สำหรับหลายแพ็คเกจคุณสามารถใช้ได้

for (package in c('<package1>', '<package2>')) {
    if (!require(package, character.only=T, quietly=T)) {
        install.packages(package)
        library(package, character.only=T)
    }
}

เคล็ดลับสำหรับมืออาชีพ:

  • เมื่อใช้ภายในสคริปต์คุณสามารถหลีกเลี่ยงหน้าจอไดอะล็อกโดยระบุreposพารามิเตอร์install.packages()เช่น

    install.packages(package, repos="http://cran.us.r-project.org")
  • คุณสามารถตัดrequire()และlibrary()เข้าsuppressPackageStartupMessages()เพื่อยับยั้งข้อความเริ่มต้นของแพ็คเกจและใช้พารามิเตอร์require(..., quietly=T, warn.conflicts=F)หากจำเป็นเพื่อให้การติดตั้งเงียบ


46

libraryการใช้งานเสมอ ไม่เคยที่ 1requireการใช้งาน

( 1แทบจะไม่เคยอาจจะ .)

สรุปนี้เป็นเพราะเมื่อใช้requireรหัสของคุณอาจจะให้ผลที่แตกต่างกันผลที่ผิดพลาดโดยไม่ต้องส่งสัญญาณความผิดพลาด นี่เป็นของหายาก แต่ไม่ใช่สมมุติ! พิจารณารหัสนี้ซึ่งให้ผลลัพธ์ที่แตกต่างกันขึ้นอยู่กับว่าสามารถโหลด {dplyr} ได้หรือไม่:

require(dplyr)

x = data.frame(y = seq(100))
y = 1
filter(x, y == 1)

ซึ่งอาจนำไปสู่ผลลัพธ์ที่ผิดพลาดอย่างละเอียด ใช้libraryแทนที่จะrequireโยนข้อผิดพลาดที่นี่ส่งสัญญาณชัดเจนว่ามีบางอย่างผิดปกติ นี้เป็นสิ่งที่ดี

นอกจากนี้ยังทำให้การดีบักความล้มเหลวอื่น ๆ ยากขึ้น: ถ้าคุณrequireทำแพ็คเกจเมื่อเริ่มต้นสคริปต์และใช้การส่งออกในบรรทัดที่ 500 คุณจะได้รับข้อความแสดงข้อผิดพลาด "ไม่พบวัตถุ" foo "ในบรรทัด 500 แทนที่จะเป็น ข้อผิดพลาด“ ไม่มีแพ็คเกจที่เรียกว่า 'bla'”

กรณีใช้งานที่ยอมรับได้เท่านั้นrequireคือเมื่อมีการตรวจสอบค่าส่งคืนทันทีตามคำตอบอื่น ๆ ที่แสดง นี่เป็นรูปแบบที่ค่อนข้างธรรมดา แต่ถึงแม้ในกรณีเหล่านี้จะเป็นการดีกว่า (และแนะนำให้ดูด้านล่าง) เพื่อแยกการตรวจสอบการมีอยู่และการโหลดของแพคเกจแทน

เพิ่มเติมเทคนิคrequireจริงโทรlibraryภายใน (ถ้าแพคเกจถูกไม่ยึดติดอยู่แล้ว - requireจึงทำการตรวจสอบซ้ำซ้อนเพราะlibrary ยังตรวจสอบไม่ว่าจะเป็นแพคเกจถูกโหลดแล้ว) นี่คือการใช้งานที่เรียบง่ายrequireเพื่อแสดงให้เห็นว่ามันทำอะไร:

require = function (package) {
    already_attached = paste('package:', package) %in% search()
    if (already_attached) return(TRUE)
    maybe_error = try(library(package, character.only = TRUE)) 
    success = ! inherits(maybe_error, 'try-error')
    if (! success) cat("Failed")
    success
}

นักพัฒนา R ที่มีประสบการณ์เห็นด้วย:

Yihui Xieผู้แต่ง {knitr}, {bookdown} และแพ็คเกจอื่น ๆพูดว่า :

ท่านสุภาพบุรุษและสุภาพสตรีฉันเคยพูดเรื่องนี้มาก่อน: require () เป็นวิธีที่ผิดในการโหลดแพ็คเกจ R; ใช้ไลบรารี () แทน

Hadley Wickhamผู้แต่งแพ็คเกจ R ยอดนิยมมากกว่าคนอื่นพูดว่า

ใช้library(x)ในสคริปต์วิเคราะห์ข้อมูล […] คุณไม่จำเป็นต้องใช้require()( requireNamespace()ดีกว่าเกือบทุกครั้ง)


ฉันจะชี้ไปที่เดียวกันเว้นแต่คุณจะเรียกใช้ฟังก์ชันทั้งหมดด้วยไวยากรณ์class::functionใช้library()เพื่อหลีกเลี่ยงปัญหานั้น
Ghost

19
?library

และคุณจะเห็น:

library(package)และrequire(package)ทั้งสองโหลดแพ็กเกจที่มีชื่อ packageและวางไว้ในรายการค้นหา requireถูกออกแบบมาเพื่อใช้ในฟังก์ชั่นอื่น ๆ ; มันกลับมาFALSEและให้คำเตือน (แทนที่จะเป็นข้อผิดพลาดเช่นเดียวกับlibrary()โดยค่าเริ่มต้น) หากแพคเกจไม่ได้อยู่ ทั้งฟังก์ชั่นตรวจสอบและอัปเดตรายการของแพ็คเกจที่โหลดอยู่ในปัจจุบันและอย่าโหลดแพ็กเกจที่โหลดแล้ว (ถ้าคุณต้องการที่จะโหลดเช่นแพคเกจโทรdetach(unload = TRUE)หรือ unloadNamespaceครั้งแรก.) requireNamespaceหากคุณต้องการโหลดแพคเกจโดยไม่ต้องใส่ไว้ในรายการค้นหาใช้


9

ทฤษฎีเริ่มต้นของฉันเกี่ยวกับความแตกต่างคือlibraryโหลดแพ็กเกจไม่ว่าจะโหลดแล้วหรือไม่นั่นคือมันอาจโหลดแพ็กเกจที่โหลดแล้วขณะที่requireตรวจสอบว่าโหลดหรือโหลดถ้าไม่ (ใช้งานในฟังก์ชัน ที่ขึ้นอยู่กับแพ็คเกจ) อย่างไรก็ตามเอกสารดังกล่าวจะทำการปฏิเสธและระบุอย่างชัดเจนว่าไม่มีฟังก์ชั่นใดที่จะโหลดแพคเกจที่โหลดแล้ว


18
สิ่งนี้น่าสนใจ แต่ไม่ใช่คำตอบสำหรับคำถามจริงๆ ... ?
Ben Bolker


3

นี่คือความแตกต่างในแพ็คเกจที่โหลดแล้ว ในขณะที่มันเป็นจริงที่ทั้งสองต้องการและห้องสมุดไม่ได้โหลดแพคเกจ ไลบรารี่ทำสิ่งอื่น ๆ มากมายก่อนที่มันจะตรวจสอบและออก

ฉันขอแนะนำให้ลบ "ต้อง" จากจุดเริ่มต้นของฟังก์ชั่นที่ใช้ 2mil ครั้งต่อไป แต่ถ้าด้วยเหตุผลบางอย่างฉันจำเป็นต้องเก็บไว้ ต้องการเป็นเทคนิคการตรวจสอบเร็วขึ้น

microbenchmark(req = require(microbenchmark), lib = library(microbenchmark),times = 100000)
Unit: microseconds
 expr    min     lq      mean median     uq        max neval
  req  3.676  5.181  6.596968  5.655  6.177   9456.006 1e+05
  lib 17.192 19.887 27.302907 20.852 22.490 255665.881 1e+05

ฉันยืนยันว่านี่เป็นเหตุผลที่ดีในการแก้ไขการติดตั้งlibraryแทน (ทั้งสองฟังก์ชั่นซึ่งส่งมาพร้อมกับ R ในปัจจุบันมีความยุ่งเหยิงมาก)
Konrad Rudolph

@KonradRudolph ดีถ้าใครบางคนกำลังจะแก้ไขไลบรารีบางทีพวกเขายังสามารถเปิดใช้งานการโหลดตามรุ่นอย่างชัดเจนและทำให้ตัวเลือกการแนบอาร์กิวเมนต์
Shape

ใช่ฉันเห็นด้วยอย่างแน่นอน แต่สิ่งเหล่านั้นจะเปลี่ยนความหมายไม่ใช่แค่การแสดง อย่างไรก็ตามการกำหนดเวอร์ชันจะไม่ทำงานกับแพ็คเกจใน R อย่างน่าเสียดาย ฉันกำลังทำงานเพื่อทดแทนสิ่งนี้ (จริง ๆ !) สำหรับการแนบคุณสามารถใช้loadNamespaceซึ่งโหลดแพ็กเกจและส่งคืนเนมสเปซโดยไม่ต้องแนบ
Konrad Rudolph
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.