137 votes

Comment puis-je filtrer les lignes au chargement dans la fonction Pandas read_csv ?

Comment puis-je filtrer les lignes d'un CSV à charger en mémoire en utilisant pandas ? T read_csv . Est-ce que je rate quelque chose ?

Exemple : nous avons un CSV avec une colonne de timestamp et nous voudrions charger seulement les lignes qui ont un timestamp plus grand qu'une constante donnée.

238voto

Matti John Points 2734

Il n'y a pas d'option pour filtrer les lignes avant que le fichier CSV ne soit chargé dans un objet pandas.

Vous pouvez soit charger le fichier et ensuite filtrer en utilisant df[df['field'] > constant] ou si vous avez un très gros fichier et que vous craignez de manquer de mémoire, utilisez un itérateur et appliquez le filtre au fur et à mesure que vous concaténerez des morceaux de votre fichier, par exemple :

import pandas as pd
iter_csv = pd.read_csv('file.csv', iterator=True, chunksize=1000)
df = pd.concat([chunk[chunk['field'] > constant] for chunk in iter_csv])

Vous pouvez varier les chunksize pour s'adapter à votre mémoire disponible. Voir aquí pour plus de détails.

10voto

Griffin Points 709

Je n'ai pas trouvé de moyen direct de le faire dans le contexte de read_csv . Cependant, read_csv renvoie un DataFrame, qui peut être filtré en sélectionnant les rangées par vecteur booléen df[bool_vec] :

filtered = df[(df['timestamp'] > targettime)]

Il s'agit de sélectionner toutes les lignes de df (en supposant que df soit un DataFrame quelconque, tel que le résultat d'une commande read_csv qui contient au moins une colonne de date. timestamp ) pour lesquels les valeurs de l timestamp sont supérieures à la valeur de targettime. Question similaire .

8voto

M. Page Points 1883

Une alternative à la réponse acceptée est d'appliquer read_csv() à un StringIO, obtenu en filtrant le fichier d'entrée.

with open(<file>) as f:
    text = "\n".join([line for line in f if <condition>])

df = pd.read_csv(StringIO(text))

Cette solution est souvent plus rapide que la réponse acceptée lorsque la condition de filtrage ne retient qu'une petite partie des lignes

4voto

mirekphd Points 11

Si la plage filtrée est contiguë (comme c'est généralement le cas avec les filtres horodateurs), la solution la plus rapide consiste à coder en dur la plage de lignes. Il suffit de combiner skiprows=range(1, start_row) con nrows=end_row paramètres. L'importation prend alors quelques secondes là où la solution acceptée prendrait des minutes. Quelques expériences avec les paramètres initiaux start_row ne représentent pas un coût énorme compte tenu des économies réalisées sur les temps d'importation. Remarquez que nous avons conservé la ligne d'en-tête en utilisant range(1,..) .

-1voto

Si vous êtes sous linux, vous pouvez utiliser grep.

# to import either on Python2 or Python3
import pandas as pd
from time import time # not needed just for timing
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

def zgrep_data(f, string):
    '''grep multiple items f is filepath, string is what you are filtering for'''

    grep = 'grep' # change to zgrep for gzipped files
    print('{} for {} from {}'.format(grep,string,f))
    start_time = time()
    if string == '':
        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)
        data = pd.read_csv(grep_data, sep=',', header=0)

    else:
        # read only the first row to get the columns. May need to change depending on 
        # how the data is stored
        columns = pd.read_csv(f, sep=',', nrows=1, header=None).values.tolist()[0]    

        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)

        data = pd.read_csv(grep_data, sep=',', names=columns, header=None)

    print('{} finished for {} - {} seconds'.format(grep,f,time()-start_time))
    return data

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X