J'ai un certain nombre de fichiers texte, disons 50, que je dois lire dans un cadre de données massif. Pour l'instant, j'utilise les étapes suivantes.
- Lisez chaque fichier et vérifiez quelles sont les étiquettes. Les informations dont j'ai besoin sont souvent contenues dans les premières lignes. Les mêmes étiquettes se répètent pour le reste du fichier, avec des types de données différents à chaque fois.
- Créez un cadre de données avec ces étiquettes.
- Lisez à nouveau le fichier et remplissez le cadre de données avec des valeurs.
- Concaténer ce cadre de données avec un cadre de données principal.
Cela fonctionne assez bien pour les fichiers de 100 Ko - quelques minutes, mais pour 50 Mo, cela prend des heures et ce n'est pas pratique.
Comment puis-je optimiser mon code ? En particulier -
- Comment puis-je identifier les fonctions qui prennent le plus de temps et que je dois optimiser ? Est-ce la lecture du fichier ? Est-ce l'écriture dans le cadre de données ? Où mon programme passe-t-il son temps ?
- Dois-je envisager le multithreading ou le multiprocessing ?
- Puis-je améliorer l'algorithme ?
- Peut-être lire le fichier entier en une seule fois dans une liste, plutôt que ligne par ligne,
- Analyse les données par morceaux ou par fichier entier, plutôt que ligne par ligne,
- Affectez les données au cadre de données par morceaux/en une seule fois, plutôt que ligne par ligne.
- Y a-t-il autre chose que je puisse faire pour que mon code s'exécute plus rapidement ?
Voici un exemple de code. Mon propre code est un peu plus complexe, car les fichiers texte sont plus complexes, de sorte que je dois utiliser environ 10 expressions régulières et plusieurs boucles while pour lire les données et les affecter au bon endroit dans le bon tableau. Pour que le MWE reste simple, je n'ai pas non plus utilisé d'étiquettes répétitives dans les fichiers d'entrée du MWE, ce qui donne l'impression que je lis le fichier deux fois sans raison. J'espère que cela a un sens !
import re
import pandas as pd
df = pd.DataFrame()
paths = ["../gitignore/test1.txt", "../gitignore/test2.txt"]
reg_ex = re.compile('^(.+) (.+)\n')
# read all files to determine what indices are available
for path in paths:
file_obj = open(path, 'r')
print file_obj.readlines()
['a 1\n', 'b 2\n', 'end']
['c 3\n', 'd 4\n', 'end']
indices = []
for path in paths:
index = []
with open(path, 'r') as file_obj:
line = True
while line:
try:
line = file_obj.readline()
match = reg_ex.match(line)
index += match.group(1)
except AttributeError:
pass
indices.append(index)
# read files again and put data into a master dataframe
for path, index in zip(paths, indices):
subset_df = pd.DataFrame(index=index, columns=["Number"])
with open(path, 'r') as file_obj:
line = True
while line:
try:
line = file_obj.readline()
match = reg_ex.match(line)
subset_df.loc[[match.group(1)]] = match.group(2)
except AttributeError:
pass
df = pd.concat([df, subset_df]).sort_index()
print df
Number
a 1
b 2
c 3
d 4
Mes fichiers d'entrée :
test1.txt
a 1
b 2
end
test2.txt
c 3
d 4
end
2 votes
Il faut probablement acheter un disque plus rapide :)
3 votes
En attendant, cherchez un bon profileur Python. Il s'agit d'un outil de type général qui vous dira quelle partie du programme est le goulot d'étranglement.
1 votes
Ne pouvez-vous pas lire l'ensemble des 50 fichiers dans un cadre de données et ensuite exécuter des manipulations basées sur des regex ? Ce sera plus rapide car les opérations de filtrage sur pandas sont très rapides.....