Разделить большой каталог файлов на n кусков, где куски приблизительно равны общему размеру файла [R] - PullRequest
0 голосов
/ 11 марта 2020

Я хотел бы разбить большой каталог файлов на отдельные списки aprox. равный общий размер файла. Идея состоит в том, чтобы разбить огромный каталог, полный csv разных размеров, на списки файлов одинакового общего размера для дальнейшей обработки.

Воспроизведение поддельных файловых данных в R:

###reproduce fake file data (just the significant columns from file.info)
filedata <- data.frame(size=sample(c(20:4000000),10000),isdir=FALSE,stringsAsFactors = F)
rownames(filedata)<-paste0("MYDIR/mycsv",c(1:nrow(filedata)),".csv")

Выходными данными (в идеале) будут данные file.frame, разделенные, например, на десять фрагментов (переменное число) приблизительно равного размера файла. количество файлов:

nchunks <- 10
listofchunks <- function(split filedata into chunks by equal size and return as list of data frames)
###ideal output would be then chunk1, chunk2, etc. -chunk10 each with a unique list of files that where the total file size cumulatively is close as possible to the other chunks. 

Спасибо!

Ответы [ 3 ]

2 голосов
/ 11 марта 2020

Другим вариантом является использование функции упаковки бункера из пакета BBmisc.

library(BBmisc)
library(dplyr)
library(tibble)

listofchunks <- filedata %>% 
  rownames_to_column() %>%
  mutate(sizeMB = size / 2^20) %>% # Avoid integer overflow by changing unit to MB
  mutate(bins = binPack(sizeMB, sum(sizeMB) / 10 * 1.01 )) %>%
  group_split(bins)

Проверьте размер ячеек:

map_dbl(listofchunks, ~ sum(.x$sizeMB))

[1] 1918.254 1918.254 1918.253 1918.253 1918.254 1918.254 1918.254 1918.254 1918.253 1728.331

Обратите внимание, что это не функция оптимизации, и последняя ячейка всегда будет самой маленькой.

0 голосов
/ 11 марта 2020

Вы можете разделить фрейм данных на децили накопленной суммы размеров файлов. Это похоже на локальное тестирование.

listofchunks <- function(path, n_chunks)
{
  filedata        <- data.frame(names = list.files(path, full.names = TRUE),          
                                stringsAsFactors = FALSE)
  filedata$sizes  <- sapply(filedata$names, file.size)
  filedata$decile <- cumsum(filedata$sizes) %/% (sum(filedata$sizes)/(n_chunks - 0.01))
  split(filedata, filedata$decile)
}
0 голосов
/ 11 марта 2020

Следующая функция может быть тем, о чем спрашивает вопрос. Не проверено.

listofchunks <- function(files, nchunks, ...){
  S <- cumsum(as.numeric(files[['size']]))
  f <- (sum(files[['size']]) %/% nchunks) * (0:(nchunks - 1))
  f <- findInterval(S, c(f, Inf))
  sp <- split(row.names(filedata), f)
  lapply(sp, function(x){
    res <- lapply(x, read.csv, ...)
    names(res) <- x
    res
  })
}

listofchunks(filedata, nchunks = 10)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...