【问题标题】:Combining or merging workspaces in R and general workspace management在 R 和常规工作空间管理中组合或合并工作空间
【发布时间】:2012-10-06 13:55:32
【问题描述】:

当一个计算系统停机/忙碌时,我经常发现自己将工作空间转移到不同的暂存驱动器等,或者,我想同时运行两个冗长的包以节省时间并在不同的地方两次加载相同的工作空间。

因此,我真的很喜欢一种查看工作区之间不同对象的方法,以及一种将它们组合在一起的方法,即仅将新的、更改的或更新的工作区对象添加到类似的工作区。这对我来说非常有用。

到目前为止,我一直依赖手动记笔记,两周后我对自己的涂鸦感到困惑。我真的只是想学习如此好的工作实践和习惯,让这种事情变得更容易。

一般来说,我真的很想了解更多关于工作空间管理的信息,以及有经验的用户如何让工作空间在长期、持续的项目中保持全面和整洁。我经常使用 Rstudio,但远程工作或使用我们的 HPC 系统可能有点滞后和笨拙,所以我倾向于使用命令行和交互式会话。

我认为制作对象列表可能是关键,但我希望能够更轻松地注释事物,可能使用用于制作对象的数据和参数等。

谢谢。

【问题讨论】:

    标签: r project workspace


    【解决方案1】:

    我认为需要在这里构建自己的功能,执行以下操作:

    • 一个接一个地加载工作区,使用:

      load()
      
    • 重命名工作区的每个元素,以防止在加载另一个工作区或将其放入列表时被覆盖

    • 检查工作区的时间戳:

      file.info()
      
    • 只保留最新的对象,然后将其保存在一些最新的工作区中

    例子:

    for(i in 1:10){
        dummy <- rnorm(1)
        Sys.sleep(1.3)
        save(dummy,file=paste("test",i,".Rdata",sep=""))
    }
    
    DUMMY <- list()
    timestamps <- NULL
    
    for(i in 1:10){
        filename <- paste("test",i,".Rdata",sep="")
        load(filename)
        DUMMY[[i]] <- dummy
        timestamps[i] <- file.info(filename)$mtime
    }
    
    uptodate <- unlist(timestamps)==max(unlist(timestamps))
    dummy <- unlist(DUMMY[uptodate])
    save(dummy,file="uptodate.Rdata")
    

    【讨论】:

    • 是的,太好了!我不知道 file.info。它不适用于工作区中的对象,是否有等效的方法?如果有一种简单的方法可以为工作区中的每个文件添加后缀/前缀,这将特别好。我认为这必须在加载之前单独完成?如果我能找到一个好的方法,也许我会再次浏览和评论。
    • "[...] 有没有等价物?"不,我不这么认为。据我所知,对象确实具有创建/修改属性。也许您可以将一个对象添加到包含这些信息的工作区(例如通过 date())。
    【解决方案2】:

    我认为关键是将您的工作区加载到单独的环境中,然后弄清楚您希望如何合并它们(如果有的话)。

    首先,让我们制作一些要保存的对象。

    set.seed(1)
    a <- data.frame(1:10, 1:10)
    b <- rnorm(10)
    

    跟踪对象创建时间的一种方法是设置属性。 缺点是您必须记住在更新时更新它 目的。 (替代方案见文章最后部分)

    d <- structure(data.frame(b), updated=Sys.time())
    attr(d, 'updated')
    #[1] "2012-10-06 12:34:06 CDT"
    

    您可以在保存工作区之前将当前时间分配给变量,以了解您何时保存它(file.info PeterM suggested 可能是更好的选择)

    updated <- Sys.time() 
    dir.create('~/tmp') # create a directory to save workspace in.
    save.image('~/tmp/ws1.RData')
    
    d[1, 1] <- 1 #make a change to `d`
    attr(d, "updated") <- Sys.time() # don't forget to update the `updated` attribute
    e <- b * a # add a new object
    updated <- Sys.time()
    save.image('~/tmp/ws2.RData')
    

    现在清除工作区,并加载工作区。但是,而不是加载它们 进入.GlobalEnv,将它们加载到自己的环境中

    rm(list=ls(all=TRUE)) # clear .GlobalEnv
    w1 <- new.env()
    w2 <- new.env()
    load('~/tmp/ws1.RData', envir=w1)
    load('~/tmp/ws2.RData', envir=w2)
    
    > ls(w1)
    [1] "a"       "b"       "d"       "updated"
    > ls(w2)
    [1] "a"       "b"       "d"       "e"       "updated"
    
    > with(w1, updated)
    [1] "2012-10-06 12:34:09 CDT"
    > with(w2, updated)
    [1] "2012-10-06 12:35:02 CDT"
    
    > attr(w1$d, 'updated')
    [1] "2012-10-06 12:34:06 CDT"
    > attr(w2$d, 'updated')
    [1] "2012-10-06 12:35:02 CDT"
    

    你可能对.ls.objects这样的功能感兴趣

    > .ls.objects(pos=w1)
                  Type Size PrettySize Rows Columns
    a       data.frame  872    [1] 872   10       2
    b          numeric  168    [1] 168   10      NA
    d       data.frame 1224   [1] 1224   10       1
    updated    POSIXct  312    [1] 312    1      NA
    > .ls.objects(pos=w2)
                  Type Size PrettySize Rows Columns
    a       data.frame  872    [1] 872   10       2
    b          numeric  168    [1] 168   10      NA
    d       data.frame 1224   [1] 1224   10       1
    e       data.frame 1032   [1] 1032   10       2
    updated    POSIXct  312    [1] 312    1      NA
    

    您可以在 assign 周围使用自定义包装器来跟踪对象的时间 已更新。

    myAssign <- function(x, value, ...) {
      attr(value, "updated") <- Sys.time()
      assign(x, value, ...)
    }
    
    > myAssign("b", w1$b[1:2], pos=w1)
    > w1$b
    [1] -0.6264538  0.1836433
    attr(,"updated")
    [1] "2012-10-06 12:44:55 CDT"
    

    最后,如果你想变得花哨,你可以做一个主动绑定,让你的对象 每当它发生变化时,总是会得到一个更新的updated 属性。

    f <- local({
      delayedAssign('x', stop('object not found'))
      function(v) {
        if (!missing(v)) x <<- structure(v, updated=Sys.time())
        x
      }
    })
    makeActiveBinding('ab', f, .GlobalEnv)
    > ab # Error, nothing has been assigned to it yet
    Error in function (v)  : object not found
    > ab <- data.frame(1:10, y=rnorm(10))
    > attr(ab, 'updated')
    [1] "2012-10-06 12:46:53 CDT"
    > ab <- data.frame(10:1, y=rnorm(10))
    > attr(ab, 'updated')
    [1] "2012-10-06 12:47:04 CDT"
    

    【讨论】:

    • +1 其他答案没有错,但我绝对认为使用环境是实现手头目标的最干净的方法。
    • 我将完成这些示例。我不知道环境。谢谢
    • @jksl,另请参阅?environment?get?assign。此外,您可以在环境中使用as.list 将其转换为您可能更习惯使用的列表。
    【解决方案3】:

    我可以回答你的部分问题,但剩下的就交给其他人了。

    假设您的工作区有许多对象,在您退出 R 之前,保存工作区并将其重命名为 .RData 为 work1.RData。如果您使用的是 linux,请尝试重命名您的文件:

    mv .RData work1.RData
    

    然后您打开一个新的 R 会话,创建任意数量的对象并像以前一样保存它。如果您想将此工作区带到其他系统,您可以重命名它。

    现在您有两个工作区 .RData 二进制文件。您可以使用

    将它们加载到单个当前工作区中
    load ("work1.RData")
    

    然后,像这样检查工作区中加载的对象

     ls() 
     objects()
    

    save.image() 在这种情况下也很有用。

    HTH

    【讨论】:

    • 谢谢,这与我已经做的非常相似,在足够大的更改或函数运行后,我会逐步进行 save.image(file="myData_1.X.RData"),但通常绝大多数对象都与少数更新、重新运行或新建的对象非常相似。我只是希望 R 中的 ls() 有更多可用的细节。如果我在 3 个不同的地方做类似的事情,那么组合更改的对象的好方法并不像上面建议的那么简单。我想我应该在创建对象时将它们写出来,在 linux 信息中制作一个日期戳。
    • 刚刚意识到,当您导入保存的对象时,属性不会保留!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多