4 votes

Traiter les fichiers volumineux par morceaux

J'ai un grand fichier qui contient deux nombres par ligne et qui est trié par la deuxième colonne. Je crée un dictionnaire de listes dont la clé est la première colonne.

Mon code se présente comme suit

from collections import defaultdict
d = defaultdict(list)
for line in fin.readline():
    vals = line.split()
    d[vals[0]].append(vals[1])
process(d)

Cependant, la taille du fichier d'entrée est trop importante. d ne tient pas dans la mémoire.

Pour contourner ce problème, je peux en principe lire des morceaux du fichier à la fois, mais je dois faire en sorte que les morceaux se chevauchent, de sorte que process(d) ne manquera rien.

En pseudo-code, je pourrais faire ce qui suit.

  1. Lire 100 lignes en créant le dictionnaire d .
  2. Traiter le dictionnaire d
  3. Supprimer tout ce qui se trouve dans d qui n'est pas à moins de 10 de la valeur maximale observée jusqu'à présent.
  4. Nous répétons l'opération, mais en nous assurant que nous n'avons pas plus de 100 lignes de données en d à tout moment.

Existe-t-il un moyen simple de faire cela en Python ?

Mise à jour. Plus de détails sur le problème. J'utiliserai d lors de la lecture d'un second fichier de paires où je produirai la paire si en fonction du nombre de valeurs dans la liste associée à la première valeur dans d qui se situent à moins de 10. Le deuxième fichier est également trié en fonction de la deuxième colonne.

Fausses données. Supposons que nous puissions placer 5 lignes de données dans la mémoire et que nous ayons besoin que le chevauchement des valeurs soit également de 5.

1 1
2 1
1 6
7 6
1 16

Donc maintenant d est {1 :[1,6,16],2 :[1],7 :[6]}.

Pour le morceau suivant, il suffit de conserver la dernière valeur (car 16-6 > 5). Nous mettrions donc

d soit {1 :[16]} et continuer à lire la suite. 4 lignes.

2voto

Kyle Kelley Points 3689

Avez-vous essayé le Bibliothèque des pandas et en particulier la lecture de vos données dans un DataFrame puis l'utilisation de par groupe sur la première colonne ?

Pandas vous permet d'effectuer efficacement de nombreuses opérations en masse sur vos données, et vous pouvez lire paresseusement si vous le souhaitez.

0voto

Tom Rose Points 464

Vous n'avez pas besoin de dict par défaut à moins qu'il ne se passe quelque chose d'étrange avec le fichier, mais vous n'avez pas mentionné ce que c'est. Utilisez plutôt une liste, qui conserve vos données dans l'ordre des lignes, de manière à pouvoir les traiter en utilisant les tranches appropriées :

d = []
for line in fin.readline():
    vals = line.split()
    d.append(vals)
    if not len(d)%100:
        process(d)
        d = d[90:]
process(d)

0voto

septi Points 5224

Vous pourriez procéder de la manière suivante :

n_process = 100
n_overlap = 10
data_chunk = []
for line in fin.readline():
    vals = line.split()
    data_chunk.append(vals)
    if len(data_chunk) == n_process:
        process(data_chunk)
        data_chunk = data_chunk[-n_overlap:]

Lors de l'utilisation d'un dictionnaire, les données peuvent être écrasées si plusieurs occurrences de nombres dans la première colonne sont présentes dans un échantillon de données. Notez également que vous devez utiliser OrderedDict puisque a dict n'a pas d'ordre en python. Cependant, à mon avis, OrderedDict est dans la plupart des cas le signe d'une mauvaise conception du code.

D'ailleurs, nous ne savons toujours pas pourquoi vous essayez de procéder de cette manière

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X