0
votes

Façon efficace de lire beaucoup de fichiers texte à l'aide de Python

J'ai environ 20000 documents dans les sous-répertoires. Et je voudrais les lire tous et les ajouter comme une liste de listes. Ceci est mon code jusqu'à présent, xxx pré>

Cependant, cela est inefficace et il faut beaucoup de temps pour lire et les ajouter dans la liste DF. Ma sortie attendue est, p>

 df= [[doc1], [doc2], [doc3], [doc4],......,[doc20000]]


10 commentaires

Je remarque que vous avez signalé cela comme «apprentissage de la machine» et, en tant que tel, je ne répondrai pas à votre question exactement, mais donnez quelques suggestions. Il s'agit généralement d'une mauvaise pratique de charger toutes vos données simultanément en mémoire, d'autant plus que vous pouvez effectuer des lectures pendant que vous effectuez vos autres calculs. Vous devez utiliser le module multiprocessionnant pour tirer parti d'un autre noyau pour aller et collecter les lots N SUIVANT N'EST Pendant que votre modèle est composé de gradients informatiques (ou quoi que ce soit). Sinon, votre code a l'air bien (pourrait être amélioré avec les gestionnaires de contexte), mais il doit être multi-fileté.


En tant que mis à part, depuis df = np.append (df, données) est en dehors de la boucle, vous jetez tout sauf les dernières données .


L'ouverture de 20 000 fichiers texte prend beaucoup de temps en soi. Peut-être que vous pourriez écrire un code séparé pour convertir celles à quelque chose comme 100 fichiers CSV qui sont beaucoup plus rapides à lire?


Supprimer le Imprimer (Données) Appelez-vous dans la boucle. Les trucs d'impression prennent une durée étonnamment longue et de tout le défilement, et il peut être encore plus lent si vous exécutez le script dans une IDE ou autre chose que le terminal.


Quelle est la taille de ces fichiers et avez-vous assez de bélier pour les tenir? Il ne faut pas prendre des heures pour lire suffisamment de données pour submerger votre RAM. À un moment donné, vous pouvez commencer à battre le fichier d'échange, mais éventuellement tout va faire exploser.


J'ai 16 Go de RAM, chaque fichier est d'environ 4 Ko-10 Ko, ils contiennent des courriels.


Oh, et @kindall a la meilleure suggestion de tous.


Ce n'est que quelques centaines de Megs .... Les lectures de fichier doivent être effectuées à la minute, pas d'heures. Ceci est un disque dur local?


Oui, j'utilise mon propre PC et toutes les données du disque dur local.


Je ne sais pas combien de copie est faite dans df = np.append (df, données) . Vous serez peut-être mieux avec une liste de python régulière et la création de la matrice NP une fois à la fin lorsque vous connaissez la taille.


3 Réponses :


0
votes

Les fonctions génératrices vous permettent de déclarer une fonction qui se comporte comme un itérateur, c'est-à-dire qu'il peut être utilisé dans une boucle pour la boucle.

Générateurs

générateur de fonctions paresseux xxx


2 commentaires

Ce n'est pas un gros fichier. Ce jeu de données contient 20000 dossiers de sous-répertoires. Mon objectif est de les lire un par un et de les annoncer dans une liste de listes.


OK, il y a un lecteur () qui mettez des données dans DataFrame et écrivez en CSV.



1
votes

Il n'y a que tant que vous pouvez faire pour accélérer l'accès des disques. Vous pouvez utiliser des threads pour chevaucher des opérations de lecture de fichier avec le (code> latin1 code> le recode et le nouveau remplacement de la nouvelle ligne. Mais de manière réaliste, cela ne fera pas une énorme différence.

import multiprocessing.pool

MEG = 2**20
filelist = []

topics =os.listdir(my_directory)
for topic in topics:
    files = os.listdir (my_directory+ '/'+ topic)
    print(files)

    for file in files: 
        print(file)
        filelist.append(my_directory+ '/'+ topic+ '/'+file)

def worker(filename):
    with open(filename, encoding ='latin1',  bufsize=1*MEG) as f:
        data = f.read().replace('\n', ' ')
        #print(data)
        return data

with multiprocessing.pool.ThreadPool() as pool:
    datalist = pool.map(worker, filelist, chunksize=1)
df = np.array(datalist)


2 commentaires

Peut-il être fait avec MPI aussi? Pouvez-vous suggérer une solution basée sur MPI?


Bien sûr, mais je pense que MPI serait plus lent, car vous devriez copier des données entre les processus. Cette tâche est probablement E / S lié et simplement laisser un thread d'attente de se lit comme une autre conversion est à propos du meilleur que vous obtiendrez.



0
votes

Note

J'ai mal lu la ligne df = np.append (df, données) et j'ai supposé que vous êtes ajouté à la mataframe, pas à la matrice numérique. Donc, mon commentaire est un peu non pertinent mais je le laissais pour d'autres que mon mal aime-moi comme moi ou que j'ai un problème similaire avec les pandas 'DataFrame ANNEX.


Problème réel

On dirait que votre question peut ne pas résoudre votre problème réel. Avez-vous mesuré la performance de vos deux appels les plus importants?

  • fichiers = os.listdir (my_directory + '/' + sujet)
  • df = np.append (df, données)

    La façon dont vous avez formaté votre code me fait penser qu'il y a un bug: df = np.append (df, données) est en dehors de la portée de la boucle afin que je ne pense que votre dernier Les données sont annexées à votre cadre de données. Si ce n'est juste un problème avec le formatage du code ici dans le poteau et que vous appendez vraiment 20k fichiers à votre trame de données, cela peut être le problème - Ajout au DataFrame est lent.

    Solution potentielle

    Comme d'habitude, les performances lentes peuvent être abordées en jetant plus de mémoire au problème. Si vous avez suffisamment de mémoire pour charger tout des fichiers à l'avance et que vous ne les insérez que dans un fichier de données ceci pourrait s'avérer plus rapide.

    La clé est de ne pas traiter d'une opération de pandas tant que vous n'avez pas chargé toutes les données. Ce n'est qu'alors que vous pouvez utiliser dataframe 's de_records ou l'une de ses autres méthodes d'usine.

    Une belle question qui a un peu plus de discussion que j'ai trouvée: Améliorer les performances de la ligne Ajout sur Pandas Dataframes

    TL; DR
    1. Mesurez le temps de lire tous les fichiers sans traiter de pandas du tout
    2. Si cela se révèle être beaucoup plus rapide et Vous avez suffisamment de mémoire pour charger tous les matières de fichiers à la fois utilisez une autre façon de construire votre Dataframe < / code>, dites dataframe.from_records


0 commentaires