使用 .onLoad() 将对象加载到 R 包中的全局环境中

Posted

技术标签:

【中文标题】使用 .onLoad() 将对象加载到 R 包中的全局环境中【英文标题】:Loading object into global environment in R Package using .onLoad() 【发布时间】:2017-12-30 20:15:45 【问题描述】:

我正在开发一个 R 包,我需要在其中管理各种对象的状态。从概念上讲,当包加载 (.onLoad) 时,它会检查缓存中的状态对象,如果不存在,则会创建一个新实例,将其保存到缓存中,并在全局环境中分配。在使用 devtools :: build() 构建站点后,我无法使用 .onLoad() 在全局环境中查看对象。所以,我有三个问题:

    .onLoad() 函数是否适合此功能?如果是这样,使状态变量在全局环境中可见的当前最佳做法是什么? 是否已开发出跨“R 会话”管理状态的解决方案(包)? 有没有比我采用的方法更好的解决问题的概念方法?

尝试过的解决方案......到目前为止

我搜索过 SE,阅读(并重新阅读)Hadley 关于 R 包的书籍,以及 Advanced R,沉思于 Winston Chang 在 R6 上的小插曲(帖子底部的链接),我将我的实验提炼为三个失败的方法。首先,这是一个简单的“GameClass”,它用三个变量来实例化一个游戏,玩家 1、玩家 2 和(游戏的)状态。

 #' GameClass
 #' \codeGameClass Class that...#'
 #' @export
 GameClass <- R6::R6Class(
   "GameClass",
   public = list(
     player1 = character(0),
     player2 = character(0),
     state  = character(0),
     initialize = function(player1, player2) 
       self$player1 <- player1
       self$player2 <- player2
       self$state <- "1st Match"
     
   )
 )

方法 1

  Assign the variable to the global environment using the <<- operator


  .onLoad <- function(libname, pkgname) 

    gameFile <- "./gameFile.Rdata"
    if (file.exists(gameFile)) 
      game <<- load(gameFile)
     else 
     game  <<- GameClass$new("Eric", "Cassie")
     save(game, file = gameFile)
     
  

方法二:

创建一个新环境并返回它

  .onLoad <- function(libname, pkgname) 
    gameFile <- "./gameFile.Rdata"
    e <- new.env()

    if (file.exists(gameFile)) 
      e$game <- load(gameFile)
     else 
      e$game <- GameClass$new("Eric", "Cassie")
      save(e$game, file = gameFile)
      
    e
  

方法3:

  .onLoad <- function(libname, pkgname) 
    gameFile <- "./gameFile.Rdata"

    if (file.exists(gameFile)) 
      game <- load(gameFile)
     else 
      game <- GameClass$new("Eric", "Cassie")
      save(game, file = gameFile)
    
    assign("game", game, envir = .GlobalEnv)
  

会话信息

 R version 3.4.1 (2017-06-30)
 Platform: x86_64-w64-mingw32/x64 (64-bit)
 Running under: Windows >= 8 x64 (build 9200)

 Matrix products: default

 locale:
 [1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United 
 States.1252    LC_MONETARY=English_United States.1252
 [4] LC_NUMERIC=C                           LC_TIME=English_United 
 States.1252    

 attached base packages:
 [1] stats     graphics  grDevices utils     datasets  methods   base     

 other attached packages:
 [1] R6Lab_0.1.0

 loaded via a namespace (and not attached):
 [1] compiler_3.4.1 R6_2.2.2       tools_3.4.1    yaml_2.1.14   

我是 OOP 的新手,R6 的新手,这是我的第一个 R 包,我已经使用 R 大约一年了。显然,我可以从这里的一些见解中受益。

提前致谢。

## References ##
[Hadley's Advanced R][1]
[Hadley's R Packages][2]
[Introduction to R6 Classes][3]
[How to define hidden global variables inside R Packages][4]
[Global variables in packages in r][5]
[Global variables in r][6]
[Global variable in a package which approach is more recommended][7]

  [1]: http://adv-r.had.co.nz/
  [2]: http://r-pkgs.had.co.nz/
  [3]: https://cran.r-project.org/web/packages/R6/vignettes/Introduction.html
  [4]: https://***.com/questions/34254716/how-to-define-hidden-global-variables-inside-r-packages
  [5]: https://***.com/questions/12598242/global-variables-in-packages-in-r
  [6]: https://***.com/questions/1236620/global-variables-in-r
  [7]: https://***.com/questions/28246952/global-variable-in-a-package-which-approach-is-more-recommended

【问题讨论】:

【参考方案1】:

应该有一个词来在显而易见的解决方案中寻找复杂的答案。再明显不过了。

R 代码工作流程

使用包的第一个实际优势是它很容易 重新加载您的代码。您可以运行 devtools::load_all(),或者在 RStudio 按 Ctrl/Cmd + Shift + L,这也保存了所有打开的文件, 节省您的击键。此键盘快捷键会导致流畅 开发工作流程:

    编辑 R 文件。 按 Ctrl/Cmd + Shift + L。 在控制台中探索代码。 冲洗并重复。

恭喜!您已经了解了您的第一个包开发工作流程。即使你从这里什么也没学到 本书,您将获得一个有用的工作流程来编辑和重新加载 R 代码

加载_all()。哇!就这么简单。 Load all 运行 .onload() 函数并将对象渲染到全局环境中。谁知道?

参考:R Code Workflow, R Packages, Hadley

【讨论】:

以上是关于使用 .onLoad() 将对象加载到 R 包中的全局环境中的主要内容,如果未能解决你的问题,请参考以下文章

SSIS包中的错误将数据加载到azure数据仓库中

如何在 R 包中正确使用其他包中的函数

R:2个不同包中的2个同名函数

R 将 poLCA 对象保存到文件

使用 R shapefile 包中的 convert.to.shapefile 将额外的数据列添加到 shapefile

如何将数据集放入 R 包中