我可以列出按日期排序的对象吗?

时间:2013-01-23 11:47:46

标签: r

这对我来说非常有用。我可以按日期(最后修改或类似的东西)对ls()的输出进行排序吗?

上下文:我的工作空间非常混乱,包含各种data.framesvariablesplots。我需要找到一个data.frame,我不记得我称它为什么,只是我最近正在研究它。因此,按修改日期排序的ls()将帮助我找出我称之为的内容。

澄清:这不是关于使用history()的问题。我经常使用历史记录,并且在我认为可能需要时经常保存它。在这种情况下,历史记录不会涵盖所需的时间段,因此我无法使用data.frame找到history()

其他:除了查找最近创建的data.frame所述的任务之外,一般来说,能够根据日期排序ls()非常有用。我在工作区中有超过100个对象,我已经工作了2年多(搜索history 2年也听起来不是很有趣)。如果有可能按时间顺序对这些对象进行排序,那么我就会知道哪些是较新的(可能是编辑过的),哪些是较旧的(也许是原始的)。

我试图通过将单个对象缓慢移动到较小的相关工作区来改进我的工作流程。但是这个过程需要时间,而且基本上没有意义(因为我接近数据分析的结束)。

6 个答案:

答案 0 :(得分:3)

嗯,通过一点创造性的黑客攻击,您可以为变量编写自己的方法。 E.g:

datedmatrix<-function(data,nrow,ncol,...) {
    output <- matrix(data, nrow=nrow,ncol=ncol,...)
    attr(output,'create') <- date()
    return(output)
}

答案 1 :(得分:3)

您可能尝试的是使用makeActiveBinding函数自动记录对感兴趣变量的修改。然后,您可以使用日志按修改时间对ls()的输出进行排序。

需要注意的是,使用此方法,必须在首次使用变量之前设置跟踪。

.change.log <- list()
track <- function(variable) {
    makeActiveBinding(variable,
        function(v) 
            if (! missing(v)) 
            .change.log[[variable]] <<- c(.change.log[[variable]], 
                                           as.list(Sys.time())),
        .GlobalEnv)
}

track('x')
x <- 1
.change.log
x <- 2
.change.log

每次修改x时,提供给makeActiveBinding的匿名函数将被调用v等于新值。在引用x时也会调用此函数,但在这种情况下没有提供给v,因此条件为missing(v) ---我们只想在值时更新日志变化。


修改

经过进一步考虑后,makeActiveBinding的更好替代方案是通过函数addTaskCallback安装修改记录器。下面的代码创建了一个自动记录器,每次在顶层使用<-运算符时,都会按变量名记录时间戳。

# define a log maker function. This returns a new logger function
# bound with a fresh log.
mk.log <- function() {
    log <- list()
    # handler functions have to have these four args, but we only use the first.
    function(expr, value, ok, visible) {
        if (class(expr) == '<-') {
            # convert the assignment call to a list, so the 
            # variable name can be extracted
            call.list <- as.list(expr)
            # extract the name of the variable being affected, and 
            # convert it to character, so we can use it as a list name
            variable <- as.character(call.list[[2]])
            # append a timestamp to the log for this variable
            log[[variable]] <<- c(log[[variable]], list(Sys.time()))
        }
        # callback handlers need to return a bool
        return(TRUE)
    }
}

# assign the handler to .log, and install it.
addTaskCallback(.log <- mk.log(), name='log')

x <- 5
x <- 10
y <- 4

# read the log
environment(.log)$log

# $x
# $x[[1]]
# [1] "2013-01-25 10:24:26.581 EST"
# 
# $x[[2]]
# [1] "2013-01-25 10:24:26.585 EST"
# 
# 
# $y
# $y[[1]]
# [1] "2013-01-25 10:24:26.589 EST"

答案 2 :(得分:2)

不,但您应该使用history功能通过您运行的最新命令查找其名称。

默认情况下,history会显示最后25行代码,但您可以执行以下操作请求:

history(max.show = 100)

您可以显示的行数也有一个硬性限制。它等于环境变量R_HISTSIZE的值,其默认值为512.但正如文档所述:

  

会话期间保留的历史记录行数没有限制[...]

所以你可以这样做:

Sys.setenv("R_HISTSIZE" = 10000)
history(max.show = 10000)

并且您应该能够在开始会话后看到所有历史记录(假设您运行的代码少于10000行。)

答案 3 :(得分:1)

您可以使用ls.str(mode="list")

示例输出:

b : 'data.frame':   1 obs. of  1 variable:
 $ test: Factor w/ 1 level "a": 1
c : 'data.frame':   1 obs. of  1 variable:
 $ x: num 1

我不认为创建时间与任何R对象一起存储。

答案 4 :(得分:0)

这不是一个直接的答案,但我个人使用RStudio。

Rstudio有一个标签历史记录(主要使用历史记录R命令),具有非常好的搜索选项。

在这里,我在历史记录中搜索词源。 enter image description here

要获得更多详细信息,我可以转到此历史记录中每行的上下文。例如,这里是第一行的细节。 enter image description here

答案 5 :(得分:0)

这是一个主意,我们创建一个日志,所有使用:=的操作都将存储在此处:

`:=` <- function(e1,e2){
  log <- data.frame(
    var = paste(collapse="\n",deparse(substitute(e1))),
    call=  paste(collapse="\n",deparse(substitute(e2))),
    time = Sys.time()
  )
  if(exists(".log",envir = .GlobalEnv)){
    assign(".log", 
           rbind(get(".log", envir = .GlobalEnv), log), 
           envir = .GlobalEnv)
  } else {
    assign(".log", log, envir = .GlobalEnv)
  }  
  eval.parent(do.call(
    substitute, list(match.call(), list(`:=` = quote(.Primitive("<-"))))))
}

x := 1
x := x+2
x
# [1] 3
.log
#   var  call                time
# 1   x     1 2019-02-26 12:17:24
# 2   x x + 2 2019-02-26 12:17:25

通过一些调整,我们还可以记录在全局环境中用<-进行的每个分配,但这会降低R的速度。

`<-` <- function(e1,e2){
  if(identical(parent.frame(), .GlobalEnv)){
    log <- data.frame(
      var = paste(collapse="\n",deparse(substitute(e1))),
      call=  paste(collapse="\n",deparse(substitute(e2))),
      time = Sys.time()
    )
    if(exists(".log",envir = .GlobalEnv)){
      assign(".log", 
             rbind(get(".log", envir = .GlobalEnv), log), 
             envir = .GlobalEnv)
    } else {
      assign(".log", log, envir = .GlobalEnv)
    }    
  } 

  eval.parent(do.call(substitute, list(
    match.call(), list(`<-` = quote(.Primitive("<-"))))))
}

rm(.log)
var <- 1
var <- var +1
var
fun <- function(x) {y <- x+1; y}
var2 <- fun(var)
var
# [1] 2
var2
# [1] 3
.log
#    var                                    call                time
# 1  var                                       1 2019-02-26 12:52:13
# 2  var                                 var + 1 2019-02-26 12:52:13
# 3  fun function(x) {\n    y <- x + 1\n    y\n} 2019-02-26 12:52:14
# 4 var2                                fun(var) 2019-02-26 12:52:14