Eu tenho tabelas muito grandes (30 milhões de linhas) que eu gostaria de carregar como quadros de dados em R. read.table()
tem muitos recursos convenientes, mas parece que há muita lógica na implementação que atrasaria as coisas. No meu caso, suponho que conheço os tipos de colunas antes do tempo, a tabela não contém nenhum cabeçalho ou nome de linha e não possui caracteres patológicos com os quais eu tenha que me preocupar.
Eu sei que a leitura em uma tabela como uma lista usando scan()
pode ser bastante rápida, por exemplo:
datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))
Mas algumas das minhas tentativas de converter isso em um quadro de dados parecem diminuir o desempenho do anterior por um fator 6:
df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))
Existe um jeito melhor de fazer isso? Ou, possivelmente, uma abordagem completamente diferente do problema?
feather
. Para ler dadosfeather
é muito mais rápido quefread
. Por exemplo, em um conjunto de dados de 4 GB que acabei de carregar,read_feather
era cerca de 4,5 vezes mais rápido quefread
. Para salvar dadosfwrite
ainda é mais rápido. blog.dominodatalab.com/the-r-data-io-shootoutfeather
é mais rápido para a leitura, mas usa muito mais espaço de armazenamento.feather
é uma boa opção. Se você se preocupa apenas em poder ler seus dados em R,rds
é preferível.Aqui está um exemplo que utiliza
fread
dadata.table
1.8.7Os exemplos vêm da página de ajuda para
fread
, com os horários no meu Windows XP Core 2 duo E8400.read.table padrão
read.table otimizado
medo
sqldf
ff / ffdf
Em suma:
fonte
fread
. Tentou lê-lo com as funções básicas R e levou cerca de 15 horas.readr
?fread
tem alguns concorrentes reais agora, poderia ser útil para adicionar valores de referência para otimizadofread
de uso - especificandocolClasses
, etc.Não vi essa pergunta inicialmente e fiz uma pergunta semelhante alguns dias depois. Vou retirar minha pergunta anterior, mas pensei em adicionar uma resposta aqui para explicar como costumava
sqldf()
fazer isso.Houve pouca discussão sobre a melhor maneira de importar 2 GB ou mais de dados de texto em um quadro de dados R. Ontem escrevi um post sobre
sqldf()
como importar os dados para o SQLite como uma área de preparação e depois sugá-los do SQLite para o R. Isso funciona muito bem para mim. Consegui extrair 2 GB (3 colunas, linhas de 40 mm) de dados em <5 minutos. Por outro lado, oread.csv
comando foi executado a noite toda e nunca foi concluído.Aqui está o meu código de teste:
Configure os dados de teste:
Reiniciei o R antes de executar a seguinte rotina de importação:
Deixei a seguinte linha rodar a noite toda, mas ela nunca foi concluída:
fonte
Estranhamente, ninguém respondeu a parte inferior da pergunta por anos, mesmo sendo importante -
data.frame
são simplesmente listas com os atributos corretos; portanto, se você possui dados grandes, não deseja usaras.data.frame
ou similares para uma lista. É muito mais rápido simplesmente "transformar" uma lista em um quadro de dados no local:Isso não faz cópia dos dados, portanto é imediato (ao contrário de todos os outros métodos). Assume que você já definiu
names()
a lista adequadamente.[Quanto ao carregamento de dados grandes no R - pessoalmente, eu os despejo por coluna em arquivos binários e o uso
readBin()
- esse é de longe o método mais rápido (além do mmapping) e é limitado apenas pela velocidade do disco. A análise de arquivos ASCII é inerentemente lenta (mesmo em C) em comparação com dados binários.]fonte
tracmem
sugere issoattr<-
eclass<-
faça cópias internamente.bit::setattr
oudata.table::setattr
não vai.df=scan(...); names(df)=...; attr...; class...
- consultetracemem()
(testado em R 2.15.2)Isso foi solicitado anteriormente no R-Help , portanto vale a pena revisar.
Uma sugestão era usar
readChar()
e, em seguida, manipular as strings no resultado comstrsplit()
esubstr()
. Você pode ver que a lógica envolvida no readChar é muito menor que a read.table.Não sei se a memória é um problema aqui, mas você também pode querer dar uma olhada no pacote HadoopStreaming . Isso usa o Hadoop , que é uma estrutura do MapReduce projetada para lidar com grandes conjuntos de dados. Para isso, você usaria a função hsTableReader. Este é um exemplo (mas tem uma curva de aprendizado para aprender o Hadoop):
A idéia básica aqui é dividir a importação de dados em partes. Você pode ir até o ponto de usar uma das estruturas paralelas (por exemplo, neve) e executar a importação de dados em paralelo, segmentando o arquivo, mas provavelmente para grandes conjuntos de dados que não ajudarão, pois você encontrará restrições de memória, é por isso que reduzir o mapa é uma abordagem melhor.
fonte
Uma alternativa é usar o
vroom
pacote. Agora no CRAN.vroom
não carrega o arquivo inteiro, indexa onde cada registro está localizado e é lido mais tarde quando você o usa.Consulte Introdução ao vroom , Introdução ao vroom e os benchmarks do vroom .
A visão geral básica é que a leitura inicial de um arquivo enorme será muito mais rápida e as modificações subsequentes nos dados poderão ser um pouco mais lentas. Portanto, dependendo do seu uso, pode ser a melhor opção.
Veja um exemplo simplificado dos benchmarks de vroom abaixo, as principais partes a serem observadas são os tempos de leitura super rápidos, mas operações ligeiramente semeadoras, como agregadas, etc.
fonte
Alguns pontos adicionais menores que vale a pena mencionar. Se você tiver um arquivo muito grande, poderá calcular rapidamente o número de linhas (se não houver cabeçalho) usando (onde
bedGraph
está o nome do seu arquivo no diretório de trabalho):Você pode então usar essa seja em
read.csv
,read.table
...fonte
Muitas vezes, acho que é apenas uma boa prática manter bancos de dados maiores dentro de um banco de dados (por exemplo, Postgres). Eu não uso nada muito maior que (nrow * ncol) ncell = 10M, que é bem pequeno; mas muitas vezes acho que quero que o R crie e mantenha gráficos intensivos de memória apenas enquanto consulta em vários bancos de dados. No futuro dos laptops de 32 GB, alguns desses tipos de problemas de memória desaparecerão. Mas o fascínio de usar um banco de dados para armazenar os dados e, em seguida, usar a memória de R para os resultados e gráficos resultantes da consulta ainda pode ser útil. Algumas vantagens são:
(1) Os dados permanecem carregados no seu banco de dados. Você simplesmente reconecta o pgadmin aos bancos de dados que deseja quando liga o laptop novamente.
(2) É verdade que R pode executar muito mais operações estatísticas e gráficas do que SQL. Mas acho que o SQL é melhor projetado para consultar grandes quantidades de dados do que R.
fonte
Estou lendo dados muito rapidamente usando o novo
arrow
pacote. Parece estar em um estágio bastante inicial.Especificamente, estou usando o formato colunar em parquet . Isso converte novamente em um
data.frame
em R, mas você pode obter velocidades ainda mais profundas se não o fizer. Esse formato é conveniente, pois também pode ser usado no Python.Meu principal caso de uso para isso está em um servidor RShiny bastante restrito. Por esses motivos, prefiro manter os dados anexados aos aplicativos (ou seja, fora do SQL) e, portanto, requer tamanho de arquivo pequeno e velocidade.
Este artigo vinculado fornece benchmarking e uma boa visão geral. Citei alguns pontos interessantes abaixo.
https://ursalabs.org/blog/2019-10-columnar-perf/
Tamanho do arquivo
Velocidade de leitura
Teste Independente
Eu realizei alguns testes independentes em um conjunto de dados simulado de 1.000.000 de linhas. Basicamente, embaralhei várias coisas para tentar desafiar a compressão. Também adicionei um pequeno campo de texto de palavras aleatórias e dois fatores simulados.
Dados
Leia e escreva
Escrever os dados é fácil.
A leitura dos dados também é fácil.
Testei a leitura desses dados em algumas das opções concorrentes e obtive resultados ligeiramente diferentes dos do artigo acima, o que é esperado.
Esse arquivo não é nem do tamanho do artigo de referência; talvez essa seja a diferença.
Testes
as_data_frame = FALSE
)arrow
)feather
)Observações
Para este arquivo em particular,
fread
é realmente muito rápido. Eu gosto do tamanho pequeno doparquet2
teste altamente compactado . Posso investir tempo para trabalhar com o formato de dados nativo, em vez dedata.frame
se realmente precisar da velocidade.Aqui
fst
também é uma ótima opção. Eu usaria ofst
formato altamente compactado ou o altamente compactado,parquet
dependendo se precisava da troca de velocidade ou tamanho do arquivo.fonte
Em vez da tabela read.t convencional, sinto que o medo é uma função mais rápida. Especificar atributos adicionais, como selecionar apenas as colunas necessárias, especificar colclasses e sequência, como fatores reduzirá o tempo necessário para importar o arquivo.
fonte
Eu tentei tudo acima e [readr] [1] fez o melhor trabalho. Tenho apenas 8gb de RAM
Loop para 20 arquivos, 5 gb cada, 7 colunas:
fonte