Comment lire des lignes spécifiques d'un grand fichier csv
Je suis en train de lire quelques lignes d'un grand fichier csv, et je ne veux pas charger tout le fichier en mémoire. L'indice des lignes spécifiques sont donnés dans une liste L = [2, 5, 15, 98, ...]
et mon fichier csv ressemble à ceci:
Col 1, Col 2, Col3
row11, row12, row13
row21, row22, row23
row31, row32, row33
...
En utilisant les idées mentionnées ici - je utiliser la commande suivante pour lire les lignes
with open('~/file.csv') as f:
r = csv.DictReader(f) # I need to read it as a dictionary for my purpose
for i in L:
for row in enumerate(r):
print row[i]
Ai immédiatement le message d'erreur suivant:
IndexError Traceback (most recent call last)
<ipython-input-25-78951a0d4937> in <module>()
6 for i in L:
7 for row in enumerate(r):
----> 8 print row[i]
IndexError: tuple index out of range
Question 1. Il semble que mon utilisation de la for
boucles ici est évidemment faux. Toutes les idées sur la façon de résoudre ce problème?
D'autre part, la suite fait le travail, mais il est trop lent:
def read_csv_line(line_number):
with open("~/file.csv") as f:
r = csv.DictReader(f)
for i, line in enumerate(r):
if i == (line_number - 2):
return line
return None
for i in L:
print read_csv_line(i)
La Question 2. Aucune idée sur la façon d'améliorer cette méthode de base d'aller à travers l'ensemble du dossier jusqu'à ce que j'atteigne la ligne je puis l'imprimer?
Vous devez vous connecter pour publier un commentaire.
Un fichier ne possède pas de "lignes" ou "lignes". Ce que vous considérez comme une "ligne" est "ce qui se trouve entre deux newline caractères". En tant que tel vous ne pouvez pas lire la nième ligne sans lire les lignes avant, que vous ne pouvais pas compter les caractères de saut de ligne.
Réponse 1: si vous pensez à votre exemple, mais avec L=[9], de dérouler vos boucles donnerait:
Comme vous pouvez le voir, la ligne est un tuple de deux membres, appelant
row[i]
signifierow[9]
, d'où le IndexError.Réponse 2: C'est très lent parce que vous êtes la lecture du fichier jusqu'à la ligne à chaque fois. Dans votre exemple, vous avez lu les 2 premières lignes, puis les 5 premiers, puis les 15 premiers, puis la première à 98, etc. Si vous avez lu les 5 premières lignes 3 fois. Vous pouvez créer un générateur qui renvoie uniquement les lignes que vous souhaitez (attention, les numéros de ligne 0-indexé):
Ainsi, lorsque vous voulez traiter les lignes, vous pouvez faire:
* Modifier *
Ce pourrait encore être amélioré pour arrêter la lecture du fichier que vous avez lu toutes les lignes que vous voulais:
En supposant
L
est une liste contenant les numéros de ligne vous le souhaitez, vous pouvez faire :De cette façon :
Le seul inconvénient est que vous avez lu tout le fichier, même si
L = [3]
i == L[0]
, et ensuite omis la première entrée deL
. Pour éviter de lire tout le fichier @vlad a donné une solution, ci-dessus.va tirer des n-uplets. Vous êtes alors essayez de sélectionner votre ith élément 2 élément n-uplet.
par exemple
En outre, depuis les dictionnaires sont des tables de hachage, votre commande initiale n'est pas nécessairement préservé. par exemple:
Juste pour résumer les grandes idées, j'ai fini par utiliser quelque chose comme ceci:
L
peuvent être triés relativement rapidement, et dans mon cas, c'était déjà triés. Ainsi, au lieu de plusieurs membres vérifie dansL
il paye pour faire le tri et ensuite seulement de vérifier chaque index sur la première entrée de elle. Voici mon bout de code:Noter que cela s'arrête dès que nous avons traversé
L
une fois.