web-dev-qa-db-fra.com

Pandas options read_csv low_memory et dtype

En appelant

df = pd.read_csv('somefile.csv')

Je reçois:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/io/parsers.py:1130: DtypeWarning: Les colonnes (4,5,7,16) ont des types mélangés. Spécifiez l'option dtype lors de l'importation ou définissez low_memory = False.

Pourquoi l'option dtype est-elle liée à low_memory et pourquoi la rendre False aiderait-elle à résoudre ce problème?

243
Josh

L'option obsolète low_memory

L'option low_memory n'est pas correctement déconseillée, mais elle devrait l'être car elle ne fait rien en réalité [ source ]

La raison pour laquelle vous recevez cet avertissement low_memory est que le fait de deviner les types pour chaque colonne est très exigeant en mémoire. Pandas tente de déterminer le type de fichier à définir en analysant les données de chaque colonne.

Dtype Guessing (très mauvais)

Les pandas ne peuvent déterminer le type de fichier qu'une colonne devrait avoir une fois que tout le fichier est lu. Cela signifie que rien ne peut vraiment être analysé avant que le fichier entier ne soit lu, à moins que vous ne risquiez de devoir changer le type de cette colonne lors de la lecture de la dernière valeur.

Prenons l'exemple d'un fichier comportant une colonne appelée user_id. Il contient 10 millions de lignes où l'id_utilisateur est toujours un nombre. Puisque pandas ne peut pas savoir qu’il ne s’agit que de nombres, il le conservera probablement comme chaîne initiale jusqu’à ce qu’il ait lu tout le fichier.

Spécifier les types (devrait toujours être fait)

ajouter

dtype={'user_id': int}

à l’appel pd.read_csv() , pandas sera informé du moment où il commencera à lire le fichier, s’il ne s’agit que d’entiers.

Il convient également de noter que si la dernière ligne du fichier avait écrit "foobar" dans la colonne user_id, le chargement se bloquerait si le type spécifié ci-dessus était spécifié.

Exemple de données cassées qui se brisent lorsque dtypes sont définis

import pandas as pd
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


csvdata = """user_id,username
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id": int, "username": object})

ValueError: invalid literal for long() with base 10: 'foobar'

les dtypes sont généralement une chose numpy, en savoir plus à leur sujet ici: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Quels types existent?

Ce sont les types numpy qui sont également acceptés dans les pandas

[numpy.generic,
 [[numpy.number,
   [[numpy.integer,
     [[numpy.signedinteger,
       [numpy.int8,
        numpy.int16,
        numpy.int32,
        numpy.int64,
        numpy.int64,
        numpy.timedelta64]],
      [numpy.unsignedinteger,
       [numpy.uint8,
        numpy.uint16,
        numpy.uint32,
        numpy.uint64,
        numpy.uint64]]]],
    [numpy.inexact,
     [[numpy.floating,
       [numpy.float16, numpy.float32, numpy.float64, numpy.float128]],
      [numpy.complexfloating,
       [numpy.complex64, numpy.complex128, numpy.complex256]]]]]],
  [numpy.flexible,
   [[numpy.character, [numpy.bytes_, numpy.str_]],
    [numpy.void, [numpy.record]]]],
  numpy.bool_,
  numpy.datetime64,
  numpy.object_]]

Pandas ajoute également deux types d’attributs: categorical et datetime64[ns, tz] qui ne sont pas disponibles dans numpy.

référence du type de pandas

Obstacles, mises en garde, notes

Le réglage de dtype=object fera taire l'avertissement ci-dessus, mais ne le rendra pas plus efficace en mémoire, mais uniquement en processus efficace.

Régler dtype=unicode ne fera rien, car pour numpy, un unicode est représenté par object.

Utilisation de convertisseurs

@sparrow indique correctement l'utilisation des convertisseurs pour éviter que pandas ne explose lorsque vous rencontrez 'foobar' dans une colonne spécifiée comme int. Je voudrais ajouter que les convertisseurs sont vraiment lourds et inefficaces à utiliser dans pandas et doivent être utilisés en dernier recours. En effet, le processus read_csv est un processus unique.

Les fichiers CSV peuvent être traités ligne par ligne et peuvent donc être traités plus efficacement par plusieurs convertisseurs en parallèle en coupant simplement le fichier en segments et en exécutant plusieurs processus, ce que pandas ne prend pas en charge. Mais c'est une histoire différente.

332
firelynx

Essayer:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

D'après la pandas documentation:

dtype: Tapez nom ou dict de colonne -> type

Quant à low_memory, il est vrai par défaut et n’est pas encore documenté. Je ne pense pas que sa pertinence si. Le message d'erreur est générique, vous ne devriez donc pas avoir besoin de manipuler low_memory de toute façon. J'espère que cela aide et laissez-moi savoir si vous avez d'autres problèmes

39
hd1
df = pd.read_csv('somefile.csv', low_memory=False)

Cela devrait résoudre le problème. J'ai eu exactement la même erreur lors de la lecture de 1,8 millions de lignes à partir d'un fichier CSV.

29
Neal

Comme mentionné précédemment par firelynx, si dtype est spécifié explicitement et que des données mixtes incompatibles avec ce type sont utilisées, le chargement se bloquera. J'ai utilisé un convertisseur comme celui-ci comme solution de contournement pour modifier les valeurs avec un type de données incompatible afin que les données puissent toujours être chargées.

def conv(val):
    if not val:
        return 0    
    try:
        return np.float64(val)
    except:        
        return np.float64(0)

df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})
14
sparrow

J'ai eu un problème similaire avec un fichier de 400 Mo. Régler low_memory=False a fait le tour pour moi. Faites les choses simples en premier, je voudrais vérifier que votre image de données n'est pas plus grande que la mémoire de votre système, redémarrez, effacez le RAM avant de continuer. Si vous rencontrez toujours des erreurs, vous devez vous assurer que votre fichier .csv est correct, jetez un coup d'œil rapide dans Excel et assurez-vous qu'il n'y a pas de corruption évidente. Des données originales brisées peuvent causer des ravages ...

1
Dr Nigel

Cela a fonctionné pour moi avec low_memory = False lors de l'importation d'un DataFrame. C'est tout le changement qui a fonctionné pour moi:

df = pd.read_csv('export4_16.csv',low_memory=False)
0
Rajat Saxena