3
votes

Lire plusieurs fichiers CSV dans Pandas en morceaux

Comment importer et lire plusieurs CSV par blocs lorsque nous avons plusieurs fichiers csv et que la taille totale de tous les csv est d'environ 20 Go?

Je ne veux pas utiliser Spark comme je le souhaite utiliser un modèle dans SkLearn donc je veux la solution dans Pandas lui-même.

Mon code est:

  allFiles = glob.glob(os.path.join(path, "*.csv"))
  df = pd.concat((pd.read_csv(f,sep=",",chunksize=10000) for f in allFiles))
  df.reset_index(drop=True, inplace=True)

Mais c'est échec car la taille totale de tout le csv dans mon chemin est de 17 Go.

Je veux le lire par morceaux mais j'obtiens une erreur si j'essaye comme ceci:

allFiles = glob.glob(os.path.join(path, "*.csv"))
df = pd.concat((pd.read_csv(f,sep=",") for f in allFiles))
df.reset_index(drop=True, inplace=True)


6 commentaires

Avez-vous essayé df = pd.concat ([pd.read_csv (f, sep = ",", chunksize = 10000) pour f dans tous les fichiers]) . C'est à dire. avec des crochets? Je pense que les supports normaux vous donnent un générateur ...


@mortysporty non n'a pas aidé. Même erreur


En regardant la documentation de pd.read_csv , il semble que la spécification de l'argument chunksize fait que l'appel de méthode renvoie un objet TextFileReader (plutôt qu'un dataframe) qui doit être répété.


Si vous n'avez pas la RAM nécessaire pour contenir le résultat de tous les morceaux, peu importe que vous le lisiez par morceaux ou non ...


@JonClements - J'ai la RAM, c'est juste que cela rend ce processus de lecture très lent et réduit les performances


Pouvez-vous fournir vos exigences matérielles? Quelle est la taille de votre RAM? Combien de CPU / GPU avez-vous?


3 Réponses :


0
votes

pour lire un gros fichier csv, vous pouvez utiliser chunksize mais dans ce cas, vous devez utiliser un itérateur comme celui-ci:

listfile = ['file1,'file2]
dfx = pd.DataFrame()
def process(d):
    #dfx=dfx.append(d) or dfx = pd.concat(dfx, d)
    #other coding

for f in listfile:
    for df in pd.read_csv(f, sep=',', iterator=True, chunksize=10000):
        process(df)

vous devez concater ou ajouter chaque morceau

ou vous pouvez le faire:

df = pd.read_csv('file.csv',, sep=',', iterator=True, chunksize=10000)
for chunk in df:
    process(chunk)

pour lire plusieurs fichiers: par exemple

for df in pd.read_csv('file.csv', sep=',', iterator=True, chunksize=10000):
    process(df)

après avoir beaucoup de fichiers vous pouvez utiliser DASK ou Pool de la bibliothèque multiprocesseur pour lancer beaucoup de processus de lecture

Quoi qu'il en soit, soit vous avez assez de mémoire, soit vous perdez du temps


3 commentaires

cela fonctionne bien si j'essaie de lire 1 csv. Mais dans mon cas, j'ai un tas de csv dans mon dossier. Donc read_csv ("file.csv") utilise juste 1 fichier ici mais j'ai un dossier avec beaucoup de csv Je suis c'est pourquoi les concaténer dans mon exemple de code


@pythonNinja je vous suggère de supprimer un maximum de données inutilisées pour votre machine learning..J'ai modifié mon programme pour lire plusieurs fichiers.


merci mais au moment où j'essaye de concater les données, j'obtiens la même erreur



0
votes

C'est une question intéressante. Je n'ai pas essayé cela, mais je pense que le code ressemblerait à quelque chose comme le script ci-dessous.

import pandas as pd
import csv
import glob
import os

#os.chdir("C:\\your_path\\")
results = pd.DataFrame([])
filelist = glob.glob("C:\\your_path\\*.csv")
#dfList=[]
for filename in filelist:
    print(filename)  
    namedf = pd.read_csv(filename, skiprows=0, index_col=0)
    results = results.append(namedf)

results.to_csv('C:\\your_path\\Combinefile.csv')


chunksize = 10 ** 6
for chunk in pd.read_csv('C:\\your_path\\Combinefile.csv', chunksize=chunksize):
    process(chunk)

Vous pourriez peut-être tout charger en mémoire et le traiter directement, mais cela prendrait probablement beaucoup plus de temps pour tout traiter.


0 commentaires

0
votes

Une façon de le faire est de fragmenter la trame de données avec pd.read_csv (fichier, chunksize = chunksize), puis si le dernier morceau que vous lisez est plus court que la taille du bloc, enregistrez le bit supplémentaire puis ajoutez-le au premier fichier du morceau suivant.

Mais assurez-vous de lire un premier morceau plus petit du fichier suivant afin qu'il corresponde à la taille totale du morceau.

def chunk_from_files(dir, master_chunksize):
    '''
    Provided a directory, loops through files and chunks out dataframes.
    :param dir: Directory to csv files.
    :param master_chunksize: Size of chunk to output.
    :return: Dataframes with master_chunksize chunk.
    '''
    files = os.listdir(dir)

    chunksize = master_chunksize
    extra_chunk = None # Initialize the extra chunk.
    for file in files:
        csv_file = os.path.join(dir, file)

        # Alter chunksize if extra chunk is not None.
        if extra_chunk is not None:
            chunksize = master_chunksize - extra_chunk.shape[0]

        for chunk in pd.read_csv(csv_file, chunksize=chunksize):
            if extra_chunk is not None: 
                # Concatenate last small chunk of previous file with altered first chunk of next file.
                chunk = pd.concat([chunk, extra_chunk])
                extra_chunk = None
                chunksize = master_chunksize # Reset chunksize.
            elif chunk.shape[0] < chunksize:
                # If last chunk is less than chunk size, set is as the extra bit.
                extra_chunk = chunk
                break

            yield chunk


0 commentaires