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?
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.
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.
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é.
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
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.
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
.
@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.
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
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.
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})
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 ...
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)