web-dev-qa-db-fra.com

Lire les lignes par numéro d'un fichier volumineux

J'ai un fichier avec 15 millions de lignes (ne tiendra pas dans la mémoire). J'ai aussi un petit vecteur de numéros de lignes - les lignes que je veux extraire.

Comment puis-je lire les lignes en un seul passage?

J'espérais une fonction C qui le fait en un seul passage.

23
Aleksandr Levchuk

L'astuce consiste à utiliser la connexion ET à l'ouvrir avant le read.table:

con<-file('filename')
open(con)

read.table(con,skip=5,nrow=1) #6-th line
read.table(con,skip=20,nrow=1) #27-th line
...
close(con)

Vous pouvez également essayer scan, il est plus rapide et donne plus de contrôle.

24
mbq

Si c'est un fichier binaire

Quelques discussions sont ici: Lecture dans seulement une partie d’un fichier Stata .DTA dans R

S'il s'agit d'un fichier CSV ou d'un autre fichier texte

S'ils sont contigus et se trouvent en haut du fichier, utilisez simplement l'argument ,nrows pour read.csv ou l'un des membres de la famille read.table. Sinon, vous pouvez combiner les arguments ,nrows et ,skip pour appeler de manière répétée read.csv (lire une nouvelle ligne ou un groupe de lignes contiguës à chaque appel), puis rbind les résultats.

5
Ari B. Friedman

Si votre fichier a des longueurs de ligne fixes, vous pouvez utiliser 'chercher' pour passer à n'importe quelle position de caractère. Il suffit donc de passer à N * line_length pour chaque N souhaité et de lire une ligne.

Cependant, à partir de la documentation R:

 Use of seek on Windows is discouraged.  We have found so many
 errors in the Windows implementation of file positioning that
 users are advised to use it only at their own risk, and asked not
 to waste the R developers' time with bug reports on Windows'
 deficiencies.

Vous pouvez également utiliser 'chercher' dans la bibliothèque C standard en C, mais je ne sais pas si l'avertissement ci-dessus s'applique également!

4
Spacedman

Avant de pouvoir obtenir une solution/réponse R, je l’ai fait en Ruby:

#!/usr/bin/env Ruby

NUM_SEQS = 14024829

linenumbers = (1..10).collect{(Rand * NUM_SEQS).to_i}

File.open("./data/uniprot_2011_02.tab") do |f|
  while line = f.gets
    print line if linenumbers.include? f.lineno 
  end
end

fonctionne vite (aussi vite que mon stockage peut lire le fichier).

3
Aleksandr Levchuk

Je compile une solution basée sur les discussions ici

scan(filename,what=list(NULL),sep='\n',blank.lines.skip = F)

Cela ne vous montrera que le nombre de lignes mais ne lira rien. Si vous voulez vraiment ignorer les lignes vides, vous pouvez simplement définir le dernier argument sur TRUE.

2
Alex Feng

Si ce n'est que lire un fichier texte en général

cat(readLines("filename.txt", n=10), sep="\n")

, où le paramètre sep sert à définir le caractère de division.

À propos de la fonction readLine, le document officiel pourrait être référencé: https://www.rdocumentation.org/packages/base/versions/3.5.1/topics/readLines

0
千木郷