【问题标题】:What ways are there for cleaning an R environment from objects?有哪些方法可以从对象中清除 R 环境?
【发布时间】:2010-05-26 16:15:25
【问题描述】:

我知道我可以使用 ls() 和 rm() 来查看和删除我的环境中存在的对象。

但是,在处理“旧”的 .RData 文件时,有时需要选择环境的一部分来查找要保留的内容和要遗漏的内容。

我想做的是有一个类似 GUI 的界面,让我可以查看对象、对它们进行排序(例如,按大小),并删除我不需要的对象(例如,按复选框界面)。既然我想这样的系统目前还没有在 R 中实现,那么存在哪些方法?你用什么来清理旧的 .RData 文件?

谢谢,

塔尔

【问题讨论】:

标签: r


【解决方案1】:

我从不创建 .RData 文件。如果您正在练习可重复的研究(并且您应该这样做!),您应该能够在 R 文件中获取从输入数据文件到所有输出的源代码。

当您的操作需要很长时间时,缓存它们是有意义的。如果经常使用这样的构造:

 if (file.exists("cache.rdata")) { 
    load("cache.rdata")
 } else {
    # do stuff ...
    save(..., file = "cache.rdata")
 }

这使您可以从缓存文件中快速工作,当您需要从头开始重新计算时,您只需删除工作目录中的所有 rdata 文件。

【讨论】:

  • 我不同意。每次加载所有文件,合并它们,准备好了吗?我选择一次性数据准备,保存到.RData并从load进行分析。
  • 嗨哈德利 - 理论上我会采取你的立场,但实际上它并不总是有效。例如,我有项目可以从哪里获得相关的 data.frame,我需要几分钟的 R 处理。在这种情况下,我宁愿做马雷克写的。
  • 缓存与这种工作实践完全正交。我添加了一条注释以使这一点更清楚。
【解决方案2】:

基本解决方案是加载您的数据,删除您不想要的数据并保存为新的、干净的数据。


处理这种情况的另一种方法是通过将加载的 RData 加载到自己的环境来控制它

sandbox <- new.env()
load("some_old.RData", sandbox)

现在你可以看到里面有什么了

ls(sandbox)
sapply(ls(sandbox), function(x) object.size(get(x,sandbox)))

那么你有几个可能性:

  • 将您想要的内容写入新的 RData:save(A, B, file="clean.RData", envir=sandbox)
  • 从环境中移除你不想要的东西rm(x, z, u, envir=sandbox)
  • 在全局工作区复制你想要的变量并删除sandbox

我通常会做类似于第三种选择的事情。加载我的数据,进行一些检查,转换,将最终数据复制到全局工作区并删除环境。


你总是可以实现你想要的。所以

  1. 加载数据
    vars &lt;- load("some_old.RData")
  2. 获取尺寸
    vars_size &lt;- sapply(vars, function(x) object.size(get(x)))
  3. 订购它们
    vars &lt;- vars[order(vars_size, decreasing=TRUE)]
    vars_size &lt;- vars_size [order(vars_size, decreasing=TRUE)]
  4. 制作对话框(取决于操作系统,这里是 Windows)
    vars_with_size &lt;- paste(vars,vars_size)
    vars_to_save &lt;- select.list(vars_with_size, multiple=TRUE)
  5. 删除不需要的内容
    rm(vars[!vars_with_size%in%vars_to_save])

为了更好的对象大小,我使用基于getAnywhere(print.object_size)的解决方案

pretty_size <- function(x) {
    ifelse(x >= 1024^3, paste(round(x/1024^3, 1L), "Gb"),
    ifelse(x >= 1024^2, paste(round(x/1024^2, 1L), "Mb"),
    ifelse(x >= 1024  , paste(round(x/1024, 1L), "Kb"),
                        paste(x, "bytes")
    )))
}

然后在4.中可以使用paste(vars, pretty_size(vars_size))

【讨论】:

  • 谢谢马雷克。您的代码对一些有趣的功能和策略很有帮助。我确实希望可以设计出像 Nico 建议的东西 - 它似乎更容易使用。再次感谢塔尔。
【解决方案3】:

您可能想查看RGtk2 包。 您可以使用 Glade Interface Designer 轻松创建一个界面,然后将您想要的任何 R 命令附加到它。

如果您想要一个好的起点来“窃取”关于如何使用RGtk2 的想法,请安装rattle 包并运行rattle();。然后看源码,开始制作自己的界面:)

我可能会尝试一下,看看我能不能想出一些简单的东西。

编辑:这是您可以使用的快速而肮脏的代码。最大的问题是,无论出于何种原因,rm 指令都没有被执行,但我不确定为什么......我知道它是中心指令,但至少接口可以工作! :D

待办事项:

  • rm 工作
  • 我将所有变量都放在remObjEnv 环境中。它不应在当前变量中列出,并且应在关闭窗口时将其删除
  • 列表只会显示全局环境中的对象,不会显示其他环境中的任何内容,但这很容易实现
  • 可能还有其他一些我没有想到的错误:D

享受

# Our environment
remObjEnv <<- new.env()

# Various required libraries
require("RGtk2")

remObjEnv$createModel <- function()
    {
    # create the array of data and fill it in
    remObjEnv$objList <- NULL
    objs <- objects(globalenv())

    for (o in objs)
        remObjEnv$objList[[length(remObjEnv$objList)+1]] <- list(object = o, 
            type = typeof(get(o)),
            size = object.size(get(o)))

    # create list store
    model <- gtkListStoreNew("gchararray", "gchararray", "gint")

    # add items 
    for (i in 1:length(remObjEnv$objList))
        {
        iter <- model$append()$iter

        model$set(iter,
              0, remObjEnv$objList[[i]]$object,
              1, remObjEnv$objList[[i]]$type,
              2, remObjEnv$objList[[i]]$size)
        }

    return(model)
    }

remObjEnv$addColumns <- function(treeview)
    {
    colNames <- c("Name", "Type", "Size (bytes)")

    model <- treeview$getModel()

    for (n in 1:length(colNames))
        {
        renderer <- gtkCellRendererTextNew()
        renderer$setData("column", n-1)
        treeview$insertColumnWithAttributes(-1, colNames[n], renderer, text=n-1)
        }
    }

# Builds the list. 
# I seem to have some problems in correctly build treeviews from glade files
# so we'll just do it by hand :)
remObjEnv$buildTreeView <- function()
    {   
    # create model
    model <- remObjEnv$createModel()
    # create tree view
    remObjEnv$treeview <- gtkTreeViewNewWithModel(model)

    remObjEnv$treeview$setRulesHint(TRUE)
    remObjEnv$treeview$getSelection()$setMode("single")

    remObjEnv$addColumns(remObjEnv$treeview)
    remObjEnv$vbox$packStart(remObjEnv$treeview, TRUE, TRUE, 0)
    }

remObjEnv$delObj <- function(widget, treeview)
    {
    model <- treeview$getModel()
    selection <- treeview$getSelection()
    selected <- selection$getSelected()
    if (selected[[1]])
        {
        iter <- selected$iter
        path <- model$getPath(iter)
            i <- path$getIndices()[[1]]
            model$remove(iter)
        }

    obj <- as.character(remObjEnv$objList[[i+1]]$object)
    rm(obj)
    }

# The list of the current objects
remObjEnv$objList <- NULL

# Create the GUI.
remObjEnv$window <- gtkWindowNew("toplevel", show = FALSE)
gtkWindowSetTitle(remObjEnv$window, "R Object Remover")
gtkWindowSetDefaultSize(remObjEnv$window, 500, 300)
remObjEnv$vbox <- gtkVBoxNew(FALSE, 5)
remObjEnv$window$add(remObjEnv$vbox)

# Build the treeview
remObjEnv$buildTreeView()

remObjEnv$button <- gtkButtonNewWithLabel("Delete selected object")
gSignalConnect(remObjEnv$button, "clicked", remObjEnv$delObj, remObjEnv$treeview)
remObjEnv$vbox$packStart(remObjEnv$button, TRUE, TRUE, 0)

remObjEnv$window$showAll()

【讨论】:

  • 谢谢尼科。如果您成功并准备好东西 - 请让我知道(tal.galili@gmail.com)谢谢!
  • @Tal Galili:我用一段代码更新了我的答案。都是你来玩的! :)
  • 嗨 Nico - 太好了,谢谢!我目前还不能玩它,因为我遇到了 Gtk2 的问题,但在修复它后,我会让你的代码运行。最好的,塔尔
  • Nico,你觉得用户___ 的想法怎么样?使用 gwidgets 而不是 RGtk2 ?
  • @Tal Galili:我从来没有用过gwidgets,我猜这是一个选项,我一般使用RGtk2,因为它很好地集成在Gnome 环境中,但这绝对是个人喜好。如果你愿意,你也可以使用 Tcl/Tk
【解决方案4】:

一旦确定了要保留的内容,就可以使用 gdata 包中的函数 -keep- 来完成其名称所暗示的工作。

a <- 1
b <- 2
library(gdata)
keep(a, all = TRUE, sure = TRUE)

有关 -all- 和 -sure- 选项的详细信息,请参阅帮助(保留)。

all: whether hidden objects (beginning with a .) should be removed, unless explicitly kept.
sure: whether to perform the removal, otherwise return names of objects that would have been removed.

这个函数非常有用,我很惊讶它不是 R 本身的一部分。

【讨论】:

    【解决方案5】:

    OS X gui 确实有这样的东西,它被称为工作区浏览器。很方便。

    我还希望有一个界面可以显示对象之间的会话依赖关系,即,如果我从 plot() 开始并向后工作以查找用于创建它的所有对象。这需要解析历史记录。

    【讨论】:

    • 谢谢肯 - 这听起来是个好主意。你知道怎么做吗?
    • 您可以使用?browseEnv浏览任何平台下的工作区。 ls.str 提供了一个控制台替代方案。
    • Richie - 谢谢,这很酷(我知道 ls.str,但不知道 browseEnv)!
    【解决方案6】:

    它没有用于删除的复选框,而是选择文件然后单击删除。但是,下面的解决方案很容易实现:

    library(gWidgets)
    options(guiToolkit="RGtk2")
    
    ## make data frame with files
    out <- lapply((x <- list.files()), file.info)
    out <- do.call("rbind", out)
    out <- data.frame(name=x, size=as.integer(out$size), ## more attributes?
                      stringsAsFactors=FALSE)
    ## set up GUI
    w <- gwindow("Browse directory")
    g <- ggroup(cont=w, horizontal=FALSE)
    tbl <- gtable(out, cont=g, multiple=TRUE)
    size(tbl) <- c(400,400)
    deleteThem <- gbutton("delete", cont=g)
    enabled(deleteThem) <- FALSE
    ## add handlers
    addHandlerClicked(tbl, handler=function(h,...) {
      enabled(deleteThem) <- (length(svalue(h$obj, index=TRUE)) > 0)
    })
    
    addHandlerClicked(deleteThem, handler=function(h,...) {
      inds <- svalue(tbl, index=TRUE)
      files <- tbl[inds,1]
      print(files)                          # replace with rm?
    })
    

    【讨论】:

    • 感谢用户。___,在我的 RGtk2 重新开始工作后,我也会尝试这个。最好的,塔尔
    • 你好,我用选项(guiToolkit="tcltk")尝试了你的代码,它部分工作。我可以看到文件表(我实际上想要 ls() 对象,但这很好) - 但我没有看到删除按钮(它没有足够的空间)。有什么想法吗?
    • 是的,这是一些我还没有弄清楚如何使用表格小部件解决的错误。几个快速技巧是:您可以手动调整窗口大小;将删除按钮移到 gtable 实例上方,或使用水平布局(在 ggroup 中跳过 Horizo​​ntal=FALSE)--John
    【解决方案7】:

    这个可怜的人的答案可能是:

    ls()
    # spot the rank of the variables you want to remove, for example 10 to 25 
    rm(list= ls()[[10:25]])
    # repeat until satisfied
    

    【讨论】:

      【解决方案8】:

      要清理整个环境,您可以尝试:

      rm(list(ls())
      

      【讨论】:

        猜你喜欢
        • 2017-08-01
        • 2012-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多