2013-02-26 9 views
9

Je veux lire un fichier texte énorme qui contient la liste des listes d'entiers. Maintenant, je fais ce qui suit:Le moyen le plus rapide pour lire l'entrée en Python

G = [] 
with open("test.txt", 'r') as f: 
    for line in f: 
     G.append(list(map(int,line.split()))) 

Cependant, il faut environ 17 secondes (via timeit). Y a-t-il un moyen de réduire ce temps? Peut-être, il y a un moyen de ne pas utiliser la carte.

+0

Essayez la liste-compréhension. –

+4

Y at-il une raison de ne pas utiliser 'numpy' ici? – DSM

+3

Définir "énorme". En outre, chaque ligne a-t-elle le même nombre d'entiers? –

Répondre

0

Le plus speedup serait d'aller pour PyPy http://pypy.org/

La question suivante ne pas lire le fichier du tout (si possible). Au lieu de le traiter comme un flux.

0

La compréhension des listes est souvent plus rapide.

G = [[int(item) item in line.split()] for line in f] 

Au-delà, essayez PyPy et Cython et numpy

+0

'G = [map (int, line.split()) pour la ligne dans f]' est plus rapide. –

+0

@StevenRumbalski Cette ligne produit des objets cartographiques: '[, , ...'. Mais la ligne @forivall fonctionne. –

+0

@BranAlgue. Aha! Vous utilisez Python 3. Donc, changez cela en 'G = [liste (carte (int, ligne.split())) pour la ligne dans f]'. Il est toujours plus rapide que la compréhension de liste imbriquée. –

0

Vous pouvez également essayer de mettre les données dans une base de données via vrac insert, le traitement puis vos dossiers avec des opérations de réglage. En fonction de ce que vous avez à faire, cela peut être plus rapide, car un logiciel d'insertion en masse est optimisé pour ce type de tâche.

1

En règle générale (pour à peu près n'importe quelle langue), l'utilisation de read() pour lire tout le fichier sera plus rapide que de lire une ligne à la fois. Si vous n'êtes pas limité par la mémoire, lisez tout le fichier en une seule fois, puis divisez les données sur les nouvelles lignes, puis parcourez la liste des lignes.

22

numpy a les fonctions loadtxt et genfromtxt, mais aucune n'est particulièrement rapide. L'un des lecteurs de texte les plus rapides disponibles dans une bibliothèque largement distribuée est la fonction read_csv dans pandas (http://pandas.pydata.org/). Sur mon ordinateur, lire 5 millions de lignes contenant deux entiers par ligne prend environ 46 secondes avec numpy.loadtxt, 26 secondes avec numpy.genfromtxt, et un peu plus de 1 seconde avec pandas.read_csv.

Voici la session montrant le résultat. (Ceci est sous Linux, Ubuntu 12.04 64 bits. Vous ne pouvez pas le voir ici, mais après chaque lecture du fichier, le cache du disque a été effacé en exécutant sync; echo 3 > /proc/sys/vm/drop_caches dans une coque séparée.)

In [1]: import pandas as pd 

In [2]: %timeit -n1 -r1 loadtxt('junk.dat') 
1 loops, best of 1: 46.4 s per loop 

In [3]: %timeit -n1 -r1 genfromtxt('junk.dat') 
1 loops, best of 1: 26 s per loop 

In [4]: %timeit -n1 -r1 pd.read_csv('junk.dat', sep=' ', header=None) 
1 loops, best of 1: 1.12 s per loop 
+0

+1, n'a pas vu ta réponse pendant que je préparais le mien. J'ai juste comparé la version de l'OP, qui prend environ 16s sur ma machine. J'ai également noté que 'loadtxt' est lent. Je ne sais pas pourquoi, je m'attendrais à ce qu'il soit plus rapide (et il devrait être plus rapide que 'genfromtxt'.) Utilise-tu aussi numpy 1.7? – bmu

+0

@bmu: Oui, j'ai utilisé numpy 1.7 –

+2

J'ai ouvert un problème numpy: https://github.com/numpy/numpy/issues/3019 Je ne peux pas m'imaginer que c'est normal que 'loadtxt' soit si lent – bmu

5

pandas qui est basé sur numpy a une base Cfile parser qui est très rapide:

# generate some integer data (5 M rows, two cols) and write it to file 
In [24]: data = np.random.randint(1000, size=(5 * 10**6, 2)) 

In [25]: np.savetxt('testfile.txt', data, delimiter=' ', fmt='%d') 

# your way 
In [26]: def your_way(filename): 
    ...:  G = [] 
    ...:  with open(filename, 'r') as f: 
    ...:   for line in f: 
    ...:    G.append(list(map(int, line.split(',')))) 
    ...:  return G   
    ...: 

In [26]: %timeit your_way('testfile.txt', ' ') 
1 loops, best of 3: 16.2 s per loop 

In [27]: %timeit pd.read_csv('testfile.txt', delimiter=' ', dtype=int) 
1 loops, best of 3: 1.57 s per loop 

Alors pandas.read_csv prend environ une seconde et demie pour lire vos données et est environ 10 fois plus vite que votre méthode.

Questions connexes