R - 在 data.frame 中存储函数

Ole*_*nge 5 r function lazy-evaluation

我想返回一个 matrix/data.frame 每行包含参数和文件的内容。

但是,可能有很多文件,所以我更愿意延迟加载文件,因此只有在请求实际内容时才会读取文件。下面的函数主动加载文件,如果as.func=F.

如果它可以延迟加载它们将是完美的,但如果不是内容而是返回一个可以读取内容的函数,这也是可以接受的。

我可以制作读取内容的函数(见下文as.func=T),但由于某种原因,我无法将其放入 data.frame 中以返回。

load_parallel_results <- function(resdir,as.func=F) {
  ## Find files called .../stdout                                                                                                                                                                              
  stdoutnames <- list.files(path=resdir, pattern="stdout", recursive=T);
  ## Find files called .../stderr                                                                                                                                                                              
  stderrnames <- list.files(path=resdir, pattern="stderr", recursive=T);
  if(as.func) {
    ## Create functions to read them                                                                                                                                                                           
    stdoutcontents <-
      lapply(stdoutnames, function(x) { force(x); return(function() { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } ) } );
    stderrcontents <-
      lapply(stderrnames, function(x) { force(x); return(function() { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } ) } );
  } else {
    ## Read them                                                                                                                                                                                               
    stdoutcontents <-
      lapply(stdoutnames, function(x) { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } );
    stderrcontents <-
      lapply(stderrnames, function(x) { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } );
  }
  if(length(stdoutnames) == 0) {
    ## Return empty data frame if no files found                                                                                                                                                               
    return(data.frame());
  }

  ## Make the columns containing the variable values                                                                                                                                                           
  m <- matrix(unlist(strsplit(stdoutnames, "/")),nrow = length(stdoutnames),byrow=T);
  mm <- as.data.frame(m[,c(F,T)]);
  ## Append the stdout and stderr column                                                                                                                                                                       
  mmm <- cbind(mm,unlist(stdoutcontents),unlist(stderrcontents));
  colnames(mmm) <- c(strsplit(stdoutnames[1],"/")[[1]][c(T,F)],"stderr");
  ## Example:                                                                                                                                                                                                  
  ## parallel --results my/res/dir --header : 'echo {};seq {myvar1}' ::: myvar1 1 2 ::: myvar2 A B                                                                                                             

  ##  > load_parallel_results("my/res/dir")                                                                                                                                                                    
  ##       myvar1 myvar2 stdout      stderr                                                                                                                                                                    
  ##  [1,] "1"    "A"    "1 A\n1"    ""                                                                                                                                                                        
  ##  [2,] "1"    "B"    "1 B\n1"    ""                                                                                                                                                                        
  ##  [3,] "2"    "A"    "2 A\n1\n2" ""                                                                                                                                                                        
  ##  [4,] "2"    "B"    "2 B\n1\n2" ""                                                                                                                                                                        
  return(mmm);
}
Run Code Online (Sandbox Code Playgroud)

背景

GNU Parallel 有一个 --results 选项,它以结构化的方式存储输出。如果有 1000000 个输出文件,可能很难管理它们。R 对此有好处,但是如果您必须读取所有 1000000 个文件来获取参数 1 = "Foo" 和参数 2 = "Bar" 的文件,那将会非常慢。

dig*_*All 5

不幸的是,我认为您不能在 data.frame 列中保存函数。但是您可以存储函数的解析文本并在需要时对其进行评估:

例如

myFunc <- function(x) { print(x) }
# convert the function to text
funcAsText <- deparse(myFunc)

# convert the text back to a function
newMyFunc <- eval(parse(text=funcAsText))

# now you can use the function newMyFunc exactly like myFunc
newMyFunc("foo")

> [1] "foo"
Run Code Online (Sandbox Code Playgroud)

编辑:
由于文件很多,我建议您简单地存储一个指示文件类型的字符串,并创建一个理解类型并相应地读取文件的函数;因此您可以在需要时通过传递类型和文件路径来调用它。