Edited at

R でパッケージの優先順位を変えたい #rstatsj

More than 3 years have passed since last update.

R で複数のパッケージを同時に使っていると、名前の衝突に困るときがあります。

例えば、dplyr パッケージの select() を使いたいのに、いつの間にか MASS パッケージが読み込まれてしまい、select() が上書きされたためにエラーになる、ということはよくあります。


R

library(dplyr)

library(MASS)

iris %>% select(Species) %>% head



結果

Error in select(., Species) : unused argument (Species)


こんなとき、パッケージの優先順位を変えられたらなぁ、と思います。

例えば、dplyr の関数を優先して使いたいときに、dplyr と指定するだけで最優先にしてくれる関数とか。

というわけで、作ってみました。(@kohske 師匠のご指摘によりめっちゃ簡単になりました → 依存関係を解決するためにまた複雑に(-_-;))


R

unload_package <- function(pkg_name) {

packages <- Filter(function(x) stringr::str_detect(x, "^package:"), search())
packages <- Map(function(x) stringr::str_replace(x, "^package:", ""), packages)
packages <- unlist(unname(packages))

if(!(pkg_name %in% packages)) {
return(pkg_name)
}

result_packages <- pkg_name
while(TRUE) {
tryCatch({
detach(paste0("package:", pkg_name), character.only = TRUE)
break
}, error = function(e) {
required_package <- stringr::str_match(e$message, pattern = "required by ‘(.+?)’")[1, 2]
required_packages <- unload_package(required_package)
result_packages <<- c(result_packages, required_packages)
})
}
unique(result_packages)
}

prior_package <- function(pkg_name) {
pkg_name <- as.character(substitute(pkg_name))
pkg_names <- unload_package(pkg_name)
for (pkg_name in pkg_names) {
suppressPackageStartupMessages(library(pkg_name, character.only = TRUE))
}
}


使い方は、dplyr の関数を優先して使いたいときに、prior_package(dplyr) と書いておくだけです。

やってみましょう。


R

library(dplyr)

library(MASS)

prior_package(dplyr)

iris %>% select(Species) %>% head



結果

  Species

1 setosa
2 setosa
3 setosa
4 setosa
5 setosa
6 setosa

できました!

MASS を優先させると


R

library(dplyr)

library(MASS)

prior_package(MASS)

iris %>% select(Species) %>% head



結果

Error in select(., Species) : unused argument (Species)


ちゃんとエラーになります!

Enjoy!