簡體   English   中英

將包附加到 R 中的“臨時”搜索路徑

[英]attaching packages to a “temporary” search path in R

在函數內部,我正在采購一個腳本:

f <- function(){
  source("~/Desktop/sourceme.R") # source someone elses script
  # do some stuff to the variables read in
}
f()
search() # library sourceme.R attaches is all the way in the back!

不幸的是,我采購的腳本並不完全在我的控制之下。 他們調用library(somePackage) ,它會污染搜索路徑。

如果sourceme.R的作者希望他/她附加的包位於頂級/接近全局環境,這主要是一個問題。 如果我自己附加了一些包來掩蓋他/她期望可用的一些函數名稱,那么這是不好的。

有沒有辦法可以獲取腳本,但以某種方式使我自己的臨時搜索路徑在函數完成運行后“重置”?

我會考慮使用callr包在單獨的 R 進程中獲取腳本,然后返回由源文件創建的環境。

通過使用單獨的 R 進程,這將防止您的搜索路徑受到污染。 我猜在您確實想要的全局環境中可能存在一些副作用(例如定義變量的新函數)。 source函數的local參數允許您指定解析腳本的執行位置。 如果您從其他 R 進程返回此環境,則可以訪問您需要的任何結果。

不確定你的樣子,但說我有這個文件可以修改搜索路徑:

# messWithSearchPath.R

library(dplyr)

a <- data.frame(groupID = rep(1:3, 10), value = rnorm(30))

b <- a %>% 
  group_by(groupID) %>% 
  summarize(agg = sum(value))

從我的頂級腳本中,我將編寫一個包裝函數以在新環境中獲取它並讓callr執行此函數:

RogueScript <- function(){
  
  rogueEnv <- new.env()
  
  source("messWIthSearchPath.R", local = rogueEnv)
  
  rogueEnv
  
}

before <- search()

scriptResults <- callr::r(RogueScript)

scriptResults$b
#>   groupID       agg
#> 1       1 -2.871642
#> 2       2  3.368499
#> 3       3  1.159509

identical(before, search())
#> [1] TRUE

如果腳本有其他副作用(例如設置選項或建立外部連接),則此方法可能不起作用。 可能有一些解決方法,具體取決於它們打算做什么,但如果您只想創建變量/函數,這應該可行。 它還可以防止腳本相互沖突,而不僅僅是頂級腳本。

一種方法是“快照”您當前的搜索路徑,然后嘗試返回到它:

search.snapshot <- local({
  .snap <- character(0)
  function(restore = FALSE) {
    if (restore) {
      if (is.null(.snap)) {
        return(character(0))
      } else {
        extras <- setdiff(search(), .snap)
        # may not work if DLLs are loaded
        for (pkg in extras) {
          suppressWarnings(detach(pkg, character.only = TRUE, unload = TRUE))
        }
        return(extras)
      }
    } else .snap <<- search()
  }
})

在行動:

search.snapshot()                                  # store current state
get(".snap", envir = environment(search.snapshot)) # view snapshot
#  [1] ".GlobalEnv"        "ESSR"              "package:stats"    
#  [4] "package:graphics"  "package:grDevices" "package:utils"    
#  [7] "package:datasets"  "package:r2"        "package:methods"  
# [10] "Autoloads"         "package:base"     
library(ggplot2)
library(zoo)
# Attaching package: 'zoo'
# The following objects are masked from 'package:base':
#     as.Date, as.Date.numeric
library(dplyr)
# Attaching package: 'dplyr'
# The following objects are masked from 'package:stats':
#     filter, lag
# The following objects are masked from 'package:base':
#     intersect, setdiff, setequal, union
search()
#  [1] ".GlobalEnv"        "package:dplyr"     "package:zoo"      
#  [4] "package:ggplot2"   "ESSR"              "package:stats"    
#  [7] "package:graphics"  "package:grDevices" "package:utils"    
# [10] "package:datasets"  "package:r2"        "package:methods"  
# [13] "Autoloads"         "package:base"     

search.snapshot(TRUE)                              # returns detached packages
# [1] "package:dplyr"   "package:zoo"     "package:ggplot2"

search()
#  [1] ".GlobalEnv"        "ESSR"              "package:stats"    
#  [4] "package:graphics"  "package:grDevices" "package:utils"    
#  [7] "package:datasets"  "package:r2"        "package:methods"  
# [10] "Autoloads"         "package:base"     

我有點自信(未經驗證)這並不總是適用於所有包,可能是由於依賴項和/或加載的 DLL。 您可以嘗試將force=TRUE添加到detach調用中,不確定這是否會更好,或者可能有其他不良副作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM