2016-03-15 7 views
1

В настоящее время я начал использовать shinyTree для одного из моих приложений, и у меня возникли проблемы с поиском эффективного способа превращения моего каталога в список. Мое предположение заключается в том, что самый простой способ - использовать что-то вроде Rcpp, чтобы использовать скорость C++, но я не женат на этой идее. Если это маршрут, тем не менее, мой навык, установленный на этой арене, практически равен нулю, поэтому я надеюсь, что кто-то сможет предоставить пару фрагментов кода, чтобы начать меня в правильном направлении.Эффективно превратить каталог файлов в список из R, возможно с Rcpp

Вот код, который я сейчас использую, чтобы добиться того, что я пытаюсь сделать:

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") 
    } 
} 

Это занимает абсурдно долгое время, и я надеюсь, что есть что-то лучше. Заранее спасибо.

ответ

3

Этот вопрос вы растете в data.frame по rbind в

file_lookup = rbind(file_lookup, tmp) 

Скорее всего в каталоге с root имеет много и много контента и, таким образом, замедление происходит при постоянно копирование и воссоздание data.frame. Вы уже имеют длину количества файлов (например, length(files)), поэтому предварительно создать data.frame с

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, которые были бы идеальными сообщениями о тренировках.

+0

a) Я не уверен, почему у меня была функция 'save' внутри цикла' for', это просто ужасная практика, и b) я должен был предварительно создать 'data.frame'. В любом случае, теперь он работает через 16 секунд, что экспоненциально быстрее, чем мой метод. Благодаря! – brittenb