[英]R function to install missing packages
對於我的一個腳本,我想編寫一個R函數來檢查是否已安裝軟件包:如果是,則應使用library()將其導入名稱空間,否則應安裝並導入。
我以為pkgname是一個字符串,並嘗試編寫如下內容:
ensure_library <- function(pkgname) {
if (!require(pkgname)) {
install.packages(pkgname, dependencies = TRUE)
}
require(pkgname)
}
如此簡單的功能無法正常工作。 如果我嘗試像ensure_library("dplyr")
一樣運行它,它將安裝dplyr軟件包,但隨后失敗,因為它dplyr
在名稱空間中導入pkgname
而不是dplyr
。
ensure_library("dplyr")
Loading required package: pkgname
Installing package into ‘/home/luca/R-dev’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/src/contrib/dplyr_0.5.0.tar.gz'
Content type 'application/x-gzip' length 708476 bytes (691 KB)
==================================================
downloaded 691 KB
* installing *source* package ‘dplyr’ ...
** package ‘dplyr’ successfully unpacked and MD5 sums checked
** libs
.... a lot of compiling here....
installing to /home/luca/R-dev/dplyr/libs
** R
** data
*** moving datasets to lazyload DB
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded
* DONE (dplyr)
The downloaded source packages are in
‘/tmp/Rtmpfd2Lep/downloaded_packages’
Loading required package: pkgname
Warning messages:
1: In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE, :
there is no package called ‘pkgname’
2: In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE, :
there is no package called ‘pkgname’
另外,如果我現在重新運行它,它將再次安裝dplyr
。
我意識到這可能是由於R非標准評估,為了使它與require
一起使用,我嘗試了幾種eval / substitute / quote組合,但我無法成功。
有人可以幫助我了解正在發生的事情以及是否有一些簡單的解決方法?
如果我已經知道一個已經實現此功能的函數,但是我真正感興趣的是理解為什么我的代碼無法按預期工作。
擴展使用character.only=TRUE
建議:如果查看require
的代碼,則會看到僅在默認值'character.only'( = FALSE
)成立時才執行第一步:
> require
function (package, lib.loc = NULL, quietly = FALSE, warn.conflicts = TRUE,
character.only = FALSE)
{
if (!character.only)
package <- as.character(substitute(package))
loaded <- paste("package", package, sep = ":") %in% search()
if (!loaded) {
if (!quietly)
packageStartupMessage(gettextf("Loading required package: %s",
package), domain = NA)
value <- tryCatch(library(package, lib.loc = lib.loc,
character.only = TRUE, logical.return = TRUE, warn.conflicts = warn.conflicts,
# snipped rest of code
因此,將character.default的默認值保留在適當的位置會強制該函數將符號pkgname
轉換為字符值。
as.character(substitute(pkgname))
[1] "pkgname"
而且由於'character.only'也是library
邏輯的一部分,並且需要調用library
,因此您可以使用library
。
進一步的評論:您發布了Rhelp的后續文章,並從Duncan Murdoch和Peter Dalgaard得到了一些有用的答案,這些答案澄清了(我希望)這個問題。 在此過程中,我想知道您是否會拒絕此答案,是因為該函數的名稱設置了一個期望,即應該進行替換,但沒有發生任何看起來像“替代”的情況。 我現在回想起來很晚,這一期望似乎是完全合理的。 我認為該函數的正確名稱應該是:replace_but_only_on_the_basis_of_the_local_environment_or_second_argument。 substitute
的更常見用法是帶有兩個參數:
y_val=45; a_val=99
substitute( x + y == z + a , list( y= y_val, a = a_val)
x + 45 == z + 99
除非在第二個參數中有一個命名項(名為env
), 否則無需“努力”檢查第一個參數中的任何符號的值。
上面給出的建議已經很好,可以解決您的問題。 盡管如此,您還是在那里重新發明了輪子。
如果您想分發R代碼,並提供對外部軟件包有要求的文檔,並且可能需要適當的測試,我建議您使用它制作一個軟件包。 安裝軟件包時,將自動確保所有依賴項均可用。 另外,您還擁有相應的文檔以及測試腳本的位置。 它可以將所有內容很好地保存在一個地方,並且可以同時進行版本控制。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.