Então, eu tenho um arquivo de dados (separados por ponto-e-vírgula) que tem muitos detalhes e linhas incompletas (levando o Access e o SQL a engasgar). É o conjunto de dados em nível de condado dividido em segmentos, subsegmentos e subsegmentos (para um total de aproximadamente 200 fatores) por 40 anos. Resumindo, é enorme e não vai caber na memória se eu tentar simplesmente lê-lo.
Portanto, minha pergunta é esta, visto que quero todos os condados, mas apenas um único ano (e apenas o nível mais alto de segmento ... levando a cerca de 100.000 linhas no final), qual seria a melhor maneira de proceder para obter este rollup em R?
Atualmente estou tentando cortar anos irrelevantes com Python, contornando o limite de tamanho de arquivo lendo e operando em uma linha de cada vez, mas prefiro uma solução apenas R (pacotes CRAN OK). Existe uma maneira semelhante de ler arquivos um pedaço por vez no R?
Quaisquer ideias seriam muito apreciadas.
Atualizar:
- Restrições
- Precisa usar minha máquina, portanto, nenhuma instância EC2
- O mais R-only possível. Velocidade e recursos não são preocupações neste caso ... desde que minha máquina não exploda ...
- Como você pode ver abaixo, os dados contêm tipos mistos, que preciso operar mais tarde
- Dados
- Os dados são 3,5 GB, com cerca de 8,5 milhões de linhas e 17 colunas
- Alguns milhares de linhas (~ 2k) estão malformadas, com apenas uma coluna em vez de 17
- Estes são totalmente sem importância e podem ser descartados
- Eu só preciso de cerca de 100.000 linhas deste arquivo (veja abaixo)
Exemplo de dados:
County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP; ...
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1; ...
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5; ...
NC [Malformed row]
[8.5 Mill rows]
Quero cortar algumas colunas e escolher dois dos 40 anos disponíveis (2009-2010 de 1980-2020), para que os dados possam caber em R:
County; State; Year; Quarter; Segment; GDP; ...
Ada County;NC;2009;4;FIRE;80.1; ...
Ada County;NC;2010;1;FIRE;82.5; ...
[~200,000 rows]
Resultados:
Depois de mexer em todas as sugestões feitas, decidi que readLines, sugerido por JD e Marek, funcionaria melhor. Dei o cheque a Marek porque ele deu uma implementação de amostra.
Reproduzi uma versão ligeiramente adaptada da implementação de Marek para minha resposta final aqui, usando strsplit e cat para manter apenas as colunas que desejo.
Também deve ser notado que isso é MUITO menos eficiente do que Python ... como em, Python chomps através do arquivo de 3,5 GB em 5 minutos enquanto R leva cerca de 60 ... mas se tudo que você tem é R, então este é o bilhete.
## Open a connection separately to hold the cursor position
file.in <- file('bad_data.txt', 'rt')
file.out <- file('chopped_data.txt', 'wt')
line <- readLines(file.in, n=1)
line.split <- strsplit(line, ';')
# Stitching together only the columns we want
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
## Use a loop to read in the rest of the lines
line <- readLines(file.in, n=1)
while (length(line)) {
line.split <- strsplit(line, ';')
if (length(line.split[[1]]) > 1) {
if (line.split[[1]][3] == '2009') {
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
}
}
line<- readLines(file.in, n=1)
}
close(file.in)
close(file.out)
Falhas por abordagem:
- sqldf
- Definitivamente, é isso que usarei para esse tipo de problema no futuro, se os dados estiverem bem formados. No entanto, se não for, o SQLite engasga.
- MapReduce
- Para ser honesto, os médicos me intimidaram um pouco, então não tive tempo de tentar. Parecia que era necessário que o objeto estivesse na memória também, o que invalidaria o ponto se fosse esse o caso.
- grande memória
- Essa abordagem vincula claramente os dados, mas só pode lidar com um tipo de cada vez. Como resultado, todos os meus vetores de caracteres caíram quando colocados em uma tabela grande. Se eu precisar projetar grandes conjuntos de dados para o futuro, porém, consideraria usar apenas números apenas para manter essa opção viva.
- Varredura
- A digitalização parecia ter problemas de tipo semelhantes aos de grande memória, mas com toda a mecânica de readLines. Em suma, simplesmente não se encaixava no projeto desta vez.
sed
e / ouawk
criar uma versão reduzida do CSV que possa ser lida diretamente. Visto que isso é mais uma solução alternativa do que uma resposta, vou deixar como um comentário.fread
função é muito mais rápida do queread.table
. Use algo comox = fread(file_path_here, data.table=FALSE)
carregá-lo como umdata.frame
objeto.Respostas:
Minha tentativa com
readLines
. Esta parte de um código criacsv
com anos selecionados.fonte
Não sou um especialista nisso, mas você pode considerar experimentar o MapReduce , o que basicamente significaria adotar uma abordagem de "dividir para conquistar". R tem várias opções para isso, incluindo:
Como alternativa, R fornece vários pacotes para lidar com grandes dados que vão para fora da memória (para o disco). Você provavelmente poderia carregar todo o conjunto de dados em um
bigmemory
objeto e fazer a redução completamente em R. Veja http://www.bigmemory.org/ para um conjunto de ferramentas para lidar com isso.fonte
bigmemory
pode ser mais fácil para você tentar primeiro, nesse caso.Sim. A função readChar () irá ler um bloco de caracteres sem assumir que eles são terminados em nulo. Se você quiser ler dados em uma linha por vez, você pode usar readLines () . Se você ler um bloco ou uma linha, fizer uma operação e depois gravar os dados, pode evitar o problema de memória. Porém, se você quiser iniciar uma instância de grande memória no EC2 da Amazon, poderá obter até 64 GB de RAM. Isso deve conter seu arquivo e mais espaço para manipular os dados.
Se você precisa de mais velocidade, a recomendação de Shane de usar Map Reduce é muito boa. No entanto, se você seguir o caminho de usar uma instância de grande memória no EC2, deverá examinar o pacote multicore para usar todos os núcleos em uma máquina.
Se quiser ler muitos GB de dados delimitados em R, você deve pelo menos pesquisar o pacote sqldf que permite importar diretamente para sqldf de R e operar os dados de dentro de R. Descobri que sqldf é um das maneiras mais rápidas de importar gigs de dados para o R, conforme mencionado na pergunta anterior .
fonte
Existe um pacote totalmente novo chamado colbycol que permite ler apenas as variáveis que você deseja de arquivos de texto enormes:
http://colbycol.r-forge.r-project.org/
Ele passa todos os argumentos para read.table, portanto, a combinação deve permitir que você crie um subconjunto bem definido.
fonte
O
ff
pacote é uma forma transparente de lidar com arquivos enormes.Você pode ver o site do pacote e / ou uma apresentação sobre ele.
Eu espero que isso ajude
fonte
Você pode importar dados para o banco de dados SQLite e usar o RSQLite para selecionar subconjuntos.
fonte
Que tal usar
readr
e aread_*_chunked
família?Então, no seu caso:
testfile.csv
Código real
Isso se aplica
f
a cada bloco, lembrando os nomes de coluna e combinando os resultados filtrados no final. Veja?callback
qual é a fonte deste exemplo.Isto resulta em:
Você pode até aumentar,
chunk_size
mas neste exemplo existem apenas 4 linhas.fonte
Já consisered bigmemory ? Verifique isso e isso .
fonte
Talvez você possa migrar para MySQL ou PostgreSQL para evitar as limitações do MS Access.
É muito fácil conectar R a esses sistemas com um conector de banco de dados baseado em DBI (disponível no CRAN).
fonte
scan () tem um argumento nlines e um argumento skip. Existe algum motivo pelo qual você pode simplesmente usar isso para ler um pedaço de linhas por vez, verificando a data para ver se é apropriada? Se o arquivo de entrada estiver ordenado por data, você pode armazenar um índice que informa qual deve ser o seu salto e nlines para acelerar o processo no futuro.
fonte
Hoje em dia, 3,5 GB simplesmente não é tão grande, posso obter acesso a uma máquina com 244 GB de RAM (r3.8xlarge) na nuvem Amazon por US $ 2,80 / hora. Quantas horas você levará para descobrir como resolver o problema usando soluções do tipo big data? Quanto vale o seu tempo? Sim, você levará uma ou duas horas para descobrir como usar a AWS - mas você pode aprender o básico em um nível gratuito, fazer upload dos dados e ler as primeiras 10k linhas em R para verificar se funcionou e, em seguida, pode iniciar um instância de grande memória como r3.8xlarge e leia tudo em! Apenas meu 2c.
fonte
Agora, 2017, eu sugeriria ir para spark e sparkR.
a sintaxe pode ser escrita de uma forma simples, bastante semelhante ao dplyr
se encaixa muito bem em memória pequena (pequena no sentido de 2017)
No entanto, pode ser uma experiência intimidante para começar ...
fonte
Eu iria para um banco de dados e, em seguida, faria algumas consultas para extrair as amostras que você precisa via DBI
Evite importar um arquivo csv de 3,5 GB para o SQLite. Ou, pelo menos, verifique se seu banco de dados ENORME se encaixa nos limites do SQLite, http://www.sqlite.org/limits.html
É um banco de dados muito grande que você tem. Eu escolheria o MySQL se você precisar de velocidade. Mas esteja preparado para esperar muitas horas pelo término da importação. A menos que você tenha algum hardware não convencional ou esteja escrevendo do futuro ...
O EC2 da Amazon pode ser uma boa solução também para instanciar um servidor executando R e MySQL.
meu valor de dois humildes centavos.
fonte