11
votes

Façon la plus efficace d'analyser un grand .csv en python?

J'ai essayé de regarder d'autres réponses mais je ne suis toujours pas sûr de la bonne façon de le faire. J'ai un certain nombre de fichiers .csv vraiment volumineux (pourraient être un gigaoctet chacun) et je souhaite d'abord obtenir leurs étiquettes de colonne, car ils ne sont pas tous identiques, puis selon les préférences de l'utilisateur, certaines de ces colonnes avec certains critères . Avant de commencer la partie Extraction, j'ai fait un test simple pour voir quel est le moyen le plus rapide d'analyser ces fichiers et voici mon code: xxx pré>

et mes résultats: p>

=======================
Populating list from Mmap
List length:  1181220
Time for completion 0.592000007629

=======================
Populating list from Fileopen
List length:  1181220
Time for completion 0.833999872208

=======================
Populating list by csv library
List length:  1181220
Time for completion 5.06700015068


4 commentaires

Code pour l'exactitude d'abord, puis pour la vitesse - c'est-à-dire. Commencez par le module csv . Si vous souhaitez effectuer plus de tests de performance au lieu de commencer par CSV , ajoutez un chèque pour vous assurer que vos autres méthodes permettent d'analyser correctement les données. Votre fichier FileOpenUsage () ressemble à un bon endroit pour ajouter un test d'exactitude.


Vos 2 premières méthodes ne analysent pas chaque ligne dans les champs. Par conséquent, vos points de repère ne mesurent pas ce que vous prétendez, ils mesurent.


Essayez le module TIMINIT dans le futur pour des points de repère comme celui-ci.


Utilisez [] pour créer des listes vides au lieu de la liste () .


4 Réponses :


1
votes

Vos 2 premières méthodes ne analysent pas chaque ligne dans les champs. La méthode csv analyse des lignes (pas les mêmes que les lignes!) Des champs.

Avez-vous vraiment besoin de construire une liste en mémoire de toutes les lignes?


6 commentaires

Je ne suis pas sûr que la mise en œuvre réelle ressemblera. Je ne sais toujours pas quel type de requêtes l'utilisateur me reviendra et, selon ces requêtes, je dois extraire les informations nécessaires des fichiers CSV. J'ai oublié de mentionner que les fichiers CSV contiennent des journaux. Une requête pourrait ressembler à: "Retourner pendant les 2 derniers jours la température (une des colonnes)"


@spagi: Veuillez Mettre à jour la question pour clarifier vos exigences. Vos points de repère mesurent Différentes choses . Vos deux premiers exemples font pas Analysez le fichier. Veuillez corriger vos points de repère pour inclure une analyse complète du fichier CSV avant de prétendre qu'elles sont plus lentes.


Mais mon intention était de faire la même chose avec tous les 3. Mettre le contenu du fichier dans une liste n'incluait pas l'analyse?


@spagi: Mettre le contenu du fichier dans une liste est un bon moyen de perdre de la mémoire si vous n'avez pas besoin de, pas quelque chose que vous devriez faire Willy-Nilly avec des fichiers de 1 Go.


Eh bien c'était pour la mesure principalement. Pour la réelle implémentation, je n'ai pas l'intention de tout mettre en mémoire. Je ne suis pas sûr du meilleur moyen encore de toute façon c'est pourquoi je cherche des conseils


@spagi: Benchmarking Les choses que vous n'allez pas utiliser dans une réelle implémentation est une perte de temps et peuvent conduire à de mauvaises décisions. Une liste de chaînes (méthodes 1 et 2) prend moins de mémoire qu'une liste de listes (méthode 3).



3
votes

Combien vous souciez-vous de la désinfection?

Le csv module est vraiment bon pour comprendre différents dialectes de fichiers CSV et veiller à ce que l'évasion soit correctement arrêtée, mais il est certainement trop excédé et peut souvent être bien plus de problèmes que cela ne vaut (surtout si vous avez unicode!)

Une implémentation vraiment naïve qui échappe correctement au \, serait: xxx

si vos données sont simples, cela fonctionnera bien. Si vous avez des données qui pourraient avoir besoin de plus d'évacuation, le csv le module est probablement votre pari le plus stable.


1 commentaires

Il lit un fichier journal, de ce que nous pouvons rassembler. Cela signifie qu'il a très peu de contrôle sur le contenu / la structure de ce qu'il lisait. Nous ne pouvons que supposer qu'il nécessite beaucoup de "désinfection" sinon des trucs se comporteront de manière incorrecte.



16
votes

Comme indiquait plusieurs autres fois, les deux premières méthodes ne font aucune analyse de chaîne réelle, elles viennent de lire une ligne à la fois sans extraire de champs. J'imagine que la majorité de la différence de vitesse observée dans le CSV est due à cela.

Le module CSV est inestimable si vous incluez des données textuelles pouvant inclure davantage de syntaxe de CSV 'standard' que de virgules, surtout si vous êtes lire à partir d'un format Excel. p>

Si vous venez de recevoir des lignes comme "1,2,3,4", vous vous êtes probablement bien avec une simple scission, mais si vous avez des lignes comme "1,2," Bonjour , mon nom \ 'S Fred' " Code> Vous allez devenir fou essayer d'analyser cela sans erreur. P>

CSV gérera également de manière transparente des choses comme les nouvelles lignes au milieu d'une chaîne citée. Un simple pour..in code> sans CSV va avoir des problèmes avec ça. P>

Le module CSV a toujours fonctionné pour moi de lire des chaînes UNICODE si je l'utilise comme:

f = csv.reader(codecs.open(filename, 'rU'))


1 commentaires

Merci beaucoup pour l'information. C'est ma première fois en python si tout compte.



2
votes

Pour lire le gros fichier CSV, nous devons créer un processus d'enfant pour lire les morceaux de fichier. Ouvrez le fichier pour obtenir l'objet de ressource de fichier. Créez un processus enfant, avec ressource comme argument. Lisez l'ensemble des lignes sous forme de morceau. Répétez les 3 étapes ci-dessus jusqu'à atteindre la fin du fichier.

from multiprocessing import Process

def child_process(name):
    # Do the Read and Process stuff here.if __name__ == '__main__':
    # Get file object resource.
    .....
    p = Process(target=child_process, args=(resource,))
    p.start()
    p.join()


0 commentaires