1

我目前开始使用shinyTree我的一个应用程序,但我很难找到一种有效的方法将我的目录变成一个列表。我的假设是,最简单的方法是使用类似的东西Rcpp来利用 C++ 的速度,但我并不认同这个想法。但是,如果这是要走的路,那么我在该领域的技能几乎为零,因此我希望有人能够提供一些代码片段,以使我朝着正确的方向开始。

这是我目前用来实现我正在尝试做的代码:

create_directory_tree = function(root) {
  tree = list()
  file_lookup = data.frame(id=character(0), file_path=character(0), stringsAsFactors=FALSE)
  files = list.files(root, all.files=F, recursive=T, include.dirs=T)

  walk_directory = function(tree, path) {
    fp = file.path(root, path)
    is_dir = file.info(fp)$isdir
    if (is.null(is_dir) | is.na(is_dir)) {
      print(fp)
      return(NULL)
    }
    path = gsub("'|\"", "", path)
    folders = str_split(path, "/")[[1]]
    if (is.na(dir) | is.null(dir)) {
      print(paste("Failed:", fp))
      return(NULL)
    }
    if (is_dir) {
      txt = paste("tree", paste("$'", folders, "'", sep="", collapse=""), " = numeric(0)", sep="")
    } else {
      txt = paste("tree", paste("$'", folders, "'", sep="", collapse=""), " = structure('', sticon='file')", sep="")
    }
    eval(parse(text = txt))
    return(tree)
  }

  for (i in 1:length(files)) {
    tmp = data.frame(id=paste0("j1_", i), file_path=file.path(root, files[i]), stringsAsFactors=FALSE)
    file_lookup = rbind(file_lookup, tmp)
    tree = walk_directory(tree, files[i])
    save(tree, file_lookup, file="www/dir_tree.Rdata")
  }
}

这花了很长时间,我希望有更好的东西。提前致谢。

4

1 回答 1

3

data.frame问题是你rbind正在成长

file_lookup = rbind(file_lookup, tmp)

可能是目录包含root大量内容,因此在不断复制和重新创建data.frame. 您已经拥有文件数量的长度(例如length(files)),因此请预先创建data.framewith

files = list.files(root, all.files=F, recursive=T, include.dirs=T)
nfiles = length(files)
file_lookup = data.frame(id=character(nfiles), file_path=character(nfiles), stringsAsFactors=FALSE)

此外,您的目标是在循环中不断保存对象的进度for,这是 I/O 瓶颈。我会搬家:

save(tree, file_lookup, file="www/dir_tree.Rdata")

在循环之外。

最后, Rcpp Gallery上有几篇文章是理想的教程文章。

于 2016-03-15T17:01:25.067 回答