2
votes

Comment lire un gros fichier tsv en python et le convertir en csv

J'ai un gros fichier tsv (environ 12 Go) que je souhaite convertir en fichier csv . Pour les fichiers tsv plus petits, j'utilise le code suivant, qui fonctionne mais est lent:

import pandas as pd

table = pd.read_table(path of tsv file, sep='\t')
table.to_csv(path andname_of csv_file, index=False)

Cependant, ce code ne fonctionne pas pour mon gros fichier, et le noyau se réinitialise au milieu.

Existe-t-il un moyen de résoudre le problème? Quelqu'un sait-il si la tâche est faisable avec Dask au lieu de Pandas?

J'utilise Windows 10.


4 commentaires

Travaillez-vous sur un système basé sur unix?


Si oui, vous pouvez simplement utiliser la commande suivante: tr '\ t' ',' output.csv , peut être modifié par un autre séparateur de champ


Je travaille sous Windows 10. Votre deuxième commentaire n'est pas clair pour moi.


Si nous avons répondu à votre question, pourriez-vous accepter une réponse / un vote favorable comme indiqué dans: stackoverflow.com/help/someone-answers


4 Réponses :


0
votes

Vous pouvez utiliser read et write intégrés à Python pour réécrire le fichier ligne par ligne. Cela peut prendre un certain temps à traiter en fonction de la taille de votre fichier, mais il ne devrait pas manquer de mémoire puisque vous travaillez ligne par ligne.

with open("input.tsv", "r") as input_file:
    for line in input_file:
        with open("output.csv", "a") as output:
            line = line.replace("\t", ",")
            output.write(line)


2 commentaires

Cette réponse devrait fonctionner, mais elle ouvre et ferme inutilement le fichier de sortie pour chaque ligne de l'entrée, ce qui peut se produire beaucoup si l'entrée est de 12 Go. Cela pourrait le ralentir beaucoup. Il serait préférable d'ouvrir le fichier de sortie en dehors de la boucle for et d'utiliser le mode 'w' au lieu de 'a'. Avec ces changements, votre réponse devient essentiellement la même que la mienne.


Je suis d'accord. J'ai écrit mon code en essayant d'être aussi lisible que possible, car OP ne semble pas avoir de connaissances dans la manipulation de fichiers texte directement via Python. Il pourrait envisager d'optimiser le code plus tard s'il en ressent le besoin, ou il pourrait le laisser tourner un peu car il en a juste besoin pour ce fichier particulier pour le moment.



3
votes

Au lieu de charger toutes les lignes en même temps en mémoire, vous pouvez lire ligne par ligne et les traiter l'une après l'autre:

Avec Python 3.x:

tr '\t' ',' <input.tsv >output.csv

Entrée (hrdata.tsv):

python tsv_csv_convertor.py > new_csv_file.csv

Sortie:

XXX

Commande:

Name,Hire Date,Salary,Sick Days remaining
Graham Chapman,03/15/14,50000.00,10
John Cleese,06/01/15,65000.00,8
Eric Idle,05/12/14,45000.00,10
Terry Jones,11/01/13,70000.00,3
Terry Gilliam,08/12/14,48000.00,7
Michael Palin,05/23/13,66000.00,8

Remarque:

Si vous utilisez un env Unix , exécutez simplement la commande:

Name    Hire Date       Salary  Sick Days remaining
Graham Chapman  03/15/14        50000.00        10
John Cleese     06/01/15        65000.00        8
Eric Idle       05/12/14        45000.00        10
Terry Jones     11/01/13        70000.00        3
Terry Gilliam   08/12/14        48000.00        7
Michael Palin   05/23/13        66000.00        8


0 commentaires

1
votes

Corrigez-moi si je me trompe, mais un fichier TSV est essentiellement un fichier CSV, utilisant un caractère de tabulation au lieu d'une virgule. Pour traduire efficacement cela en python, vous devez parcourir les lignes de votre fichier source, remplacer les onglets par des virgules et écrire la nouvelle ligne dans le nouveau fichier. Vous n'avez pas besoin d'utiliser de module pour ce faire, écrire la solution en Python est en fait assez simple:

from io import FileIO

# This chunk size loads 1MB at a time for conversion.
CHUNK_SIZE = 1 << 20


def tsv_to_csv_BIG(filename):
    ext_index = filename.rfind('.tsv')
    if ext_index == -1:
        new_filename = filename + '.csv'
    else:
        new_filename = filename[:ext_index] + '.csv'

    original = FileIO(filename, 'r')
    new = FileIO(new_filename, 'w')
    table = bytes.maketrans(b'\t', b',')

    while True:
        chunk = original.read(CHUNK_SIZE)
        if len(chunk) == 0:
            break
        new.write(chunk.translate(table))

    original.close()
    new.close()
    return new_filename

L'itération des lignes comme celle-ci ne charge chaque ligne en mémoire qu'une par une, au lieu de charger le tout en mémoire. Le traitement de 12 Go de données peut toutefois prendre un certain temps.

MISE À JOUR: En fait, maintenant que j'y pense, il peut être beaucoup plus rapide d'utiliser les E / S binaires sur un fichier aussi volumineux, puis de remplacer les onglets par des virgules sur de gros morceaux du fichier à la fois. Ce code suit cette stratégie:

def tsv_to_csv(filename):
    ext_index = filename.rfind('.tsv')
    if ext_index == -1:
        new_filename = filename + '.csv'
    else:
        new_filename = filename[:ext_index] + '.csv'

    with open(filename) as original, open(new_filename, 'w') as new:
        for line in original:
            new.write(line.replace('\t', ','))

    return new_filename

Sur mon ordinateur portable utilisant un fichier TSV de 1 Go, la première fonction prend 4 secondes pour se traduire en CSV tandis que la deuxième fonction prend 1 seconde. Le réglage du paramètre CHUNK_SIZE pourrait l'accélérer davantage si votre stockage peut suivre, mais 1 Mo semble être le point idéal pour moi.

L'utilisation de tr comme mentionné dans une autre réponse a pris 3 secondes pour moi, donc l'approche python fragmentée semble la plus rapide.


0 commentaires

0
votes

Vous pouvez utiliser chunksize pour parcourir le fichier entier en morceaux. Notez que cela utilise .read_csv () au lieu de .read_table()

df = pd.DataFrame()
for chunk in pd.read_csv('Check1_900.csv', header=None, names=['id', 'text', 'code'], chunksize=1000):
    df = pd.concat([df, chunk], ignore_index=True)

source


Vous pouvez également essayer l'indicateur low_memory = False (source ).


Et ensuite serait le memory_map (faites défiler vers le bas à https://pandas.pydata.org/pandas-docs/stable/ reference / api / pandas.read_csv.html )

memory_map : booléen, par défaut False

Si un chemin de fichier est fourni pour filepath_or_buffer, mappez l'objet fichier directement sur la mémoire et accédez directement aux données à partir de là. L'utilisation de cette option peut améliorer les performances car il n'y a plus de surcharge d'E / S.

Notez que to_csv () a des fonctionnalités similaires.


0 commentaires