Estou tentando ler várias tabelas compactadas com mais de 5 GB de tamanho em R e, como não tenho memória suficiente para lê-las todas de uma vez, preciso processá-las um pedaço de cada vez, por exemplo, as primeiras 1.000 linhas de cada arquivo, depois as próximas 1.000 linhas de cada arquivo, etc. Sei como manter um arquivo aberto com um cursor ou ponteiro de arquivo salvo basicamente em qualquer linguagem diferente de R. Como posso fazer isso aqui?
Atualmente estou fazendo algo parecido com isto:
library(data.table)
library(R.utils)
inFiles = c("file1.tsv.gz", "file2.tsv.gz", "file3.tsv.gz")
totallines <- 10000
chunksize <- 1000
iters <- 1
skip_val <- 0
max_iters <- ceiling(totallines/chunksize)
while (iters <= max_iters) {
data = lapply(inFiles,function(file) {
data.table::fread(file, nrows=chunksize, skip=skip_val,
col.names=data_colnames, sep="\t")
})
# Process the data in omitted code here
# Move on to the next chunk
iters = iters + 1
skip_val = skip_val + chunksize
}
O problema é que esses arquivos são grandes e compactados, e quanto menor o chunksize ou maior o arquivo, o programa gasta mais e mais tempo apenas lendo por causa das linhas puladas. Toda vez que ele lê o próximo chunk, ele também tem que descompactar e pular todas as linhas anteriores.
Dei uma olhada em readr::read_delim_chunked , mas não tenho certeza de como poderia usá-lo para iterar por muitos arquivos de uma vez.
Você está procurando por
pipe()
. Quando usado dentro de um loop comorepeat()
,readLines()
continua da posição atual — ele não reiniciagunzip
ou descomprime novamente o conteúdo anterior.Observação: a solução atual pressupõe que há apenas dados nos .tsvs, sem cabeçalho.
Uso
Arquivo único:
Vários arquivos:
No Linux podemos usar
parallel::mclapply
:Alternativa Aprimorada
Não há necessidade de especificar linhas totais; uma função flexível (
FX
) é aplicada por pedaço, linhas de metadados (skip
) podem ser ignoradas e aheader
é suportado. O comando shell (unz
) é personalizável para qualquer ferramenta de descompressão.matrix
cálculos são suportados por padrão e um aviso é emitido se o último pedaço for menor do que o esperado.Exemplo em que o total de linhas não é divisível pelo tamanho do bloco (por exemplo,
m <- 1e5 - 1
em Dados, infra):Dados:
(Para Linux. Oito arquivos serão criados no diretório atual.)