2015-07-27 4 views
2

Я регулярно получаю данные от источника, который производит нестандартный формат Excel, который не может быть прочитан readxl::read_excel. Вот github issue thread. Следовательно, у меня есть полное дерево каталогов, содержащее сотни (почти) файлов Excel, которые я хотел бы прочитать в R, и объединять их с plyr::ldply. Однако файлы могут быть открыты только на XLConnect::loadWorkbook. Но, к сожалению, даже при распределении огромных объемов памяти для виртуальной машины Java она всегда сбой после чтения нескольких файлов. Я попытался добавить эти три строки в моей функции импорта:Итеративно сохранять дерево каталогов файлов Excel

options(java.parameters = "-Xmx16g") 
detach("package:XLConnect", unload = TRUE) 
library(XLConnect) 
xlcFreeMemory() 

Однако, я все еще получаю:

Error: OutOfMemoryError (Java): Java heap space

Все, что мне нужно сделать, это пересохраните их в Excel, а затем они читают в просто отлично от readxl::read_excel , Я надеюсь, что смогу также переустановить их в пакетном режиме, используя XLConnect, а затем прочитайте их, используя readxl::read_excel. К сожалению, используя Linux, я не могу просто переписать Excel для их сохранения. У кого-нибудь есть другой способ обхода?

+0

Может быть, вы могли бы партию пересохранить XLS с помощью макроса - STH в венах http://answers.microsoft.com/en-us/office/ форум/office_2010-первенствует/как к I-Batch-Convert-сотни-оф-первенствовать-2007/7d608c2e-67fa-48df-94b2-a5b6464d8172 – lukeA

ответ

1

Поскольку вы работаете в Linux, запуск макроса Excel для повторного сохранения таблиц выглядит сложным.

Вы можете запустить отдельный процесс R для чтения каждой электронной таблицы с помощью XLConnect. Это может быть сделано, по крайней мере, двумя способами:

  • Run Rscript с файлом сценария, передав ему имя таблицы. Сохраните данные в файле .RData и прочитайте его в процессе основного R.

  • Используйте parLapply из параллельного пакета, передавая ему вектор имен таблиц и функцию для чтения файла. В этом случае вам не нужно сохранять данные на диск в качестве промежуточного шага. Однако вам может потребоваться сделать это в кусках, так как подчиненные процессы будут медленно исчерпать память, если вы не перезапустите их.

Пример последние:

files <- list.files(pattern="xlsx$") 
filesPerChunk <- 5 
clustSize <- 4 # or how ever many slave nodes you want 
runSize <- clustSize * filesPerChunk 

runs <- length(files)%/%runSize + (length(files)%%runSize != 0) 

library(parallel) 

sheets <- lapply(seq(runs), function(i) { 
    runStart <- (i - 1) * runSize + 1 
    runEnd <- min(length(files), runStart + runSize - 1) 
    runFiles <- files[runStart:runEnd] 

    # periodically restart and stop the cluster to deal with memory leaks 
    cl <- makeCluster(clustSize) 
    on.exit(stopCluster(cl)) 

    parLapply(cl, runFiles, function(f) { 
     require(XLConnect) 
     loadWorkbook(f, ...) 
    }) 
}) 

sheets <- unlist(sheets, recursive=FALSE) # convert list of lists to a simple list 
Смежные вопросы