web-dev-qa-db-fra.com

Erreur de mémoire lors de l’utilisation de pandas read_csv

J'essaie de faire quelque chose d'assez simple, en lisant un gros fichier csv dans un fichier de données pandas).

data = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2)

Le code échoue avec un MemoryError ou ne finit jamais.

L'utilisation de Mem dans le gestionnaire de tâches s'est arrêtée à 506 Mo. Après 5 minutes sans changement ni activité du processeur dans le processus, je l'ai arrêté.

J'utilise pandas version 0.11.0.

Je suis conscient qu'il y avait un problème de mémoire avec l'analyseur de fichier, mais selon http://wesmckinney.com/blog/?p=54 cela aurait dû être corrigé.

Le fichier que j'essaye de lire est de 366 Mo. Le code ci-dessus fonctionne si je coupe le fichier en fichier bref (25 Mo).

Il est également arrivé que je reçois un message m'indiquant qu'il ne peut pas écrire à l'adresse 0x1e0baf93 ...

Trace de la pile:

Traceback (most recent call last):
  File "F:\QA ALM\Python\new WIM data\new WIM data\new_WIM_data.py", line 25, in
 <module>
    wimdata = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2
)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 401, in parser_f
    return _read(filepath_or_buffer, kwds)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 216, in _read
    return parser.read()
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 643, in read
    df = DataFrame(col_dict, columns=columns, index=index)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 394, in __init__
    mgr = self._init_dict(data, index, columns, dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 525, in _init_dict
    dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 5338, in _arrays_to_mgr
    return create_block_manager_from_arrays(arrays, arr_names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1820, in create_block_manager_from_arrays
    blocks = form_blocks(arrays, names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1872, in form_blocks
    float_blocks = _multi_blockify(float_items, items)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1930, in _multi_blockify
    block_items, values = _stack_arrays(list(tup_block), ref_items, dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1962, in _stack_arrays
    stacked = np.empty(shape, dtype=dtype)
MemoryError
Press any key to continue . . .

Un peu d’arrière-plan - j’essaie de convaincre les gens que Python peut faire la même chose que R.). J’essaie de reproduire un script R qui

data <- read.table(paste(INPUTDIR,config[i,]$TOEXTRACT,sep=""), HASHEADER, DELIMITER,skip=2,fill=TRUE)

R parvient non seulement à lire correctement le fichier ci-dessus, il lit même plusieurs de ces fichiers dans une boucle for (puis effectue des opérations avec les données). Si Python a un problème avec les fichiers de cette taille, je pourrais peut-être mener une bataille perdue ...

78
Anne

Limite de mémoire Windows

Les erreurs de mémoire se produisent souvent avec python lorsque vous utilisez la version 32 bits de Windows. En effet, les processus 32 bits ne reçoit que 2 Go de mémoire avec laquelle jouer par défaut.

Astuces pour réduire l'utilisation de la mémoire

Si vous n'utilisez pas 32bit python dans Windows mais cherchez à améliorer l'efficacité de votre mémoire lors de la lecture de fichiers CSV, il existe une astuce.

La fonction pandas.read_csv utilise une option appelée dtype. Ceci permet à pandas) de savoir quels types existent dans vos données csv.

Comment ça marche

Par défaut, pandas essaiera de deviner quels types ont votre type de fichier csv. Il s’agit d’une opération très lourde, car lors de la détermination du type, il doit conserver toutes les données brutes sous forme d’objets (chaînes) en mémoire.

Exemple

Disons que votre csv ressemble à ceci:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01

Cet exemple ne pose évidemment pas de problème pour la lecture en mémoire, mais ce n’est qu’un exemple.

Si pandas devait lire le fichier csv ci-dessus sans aucune option de type dtype, l'âge serait stocké sous forme de chaînes en mémoire jusqu’à ce que pandas ait lu suffisamment de lignes du fichier csv pour pouvoir deviner.

Je pense que la valeur par défaut dans pandas) est de lire 1 000 000 de lignes avant de deviner le type.

Solution

En spécifiant dtype={'age':int} En tant qu'option pour la .read_csv() laisserons pandas) savoir que l'âge doit être interprété comme un nombre. Cela vous permet d'économiser beaucoup de mémoire.

Problème avec des données corrompues

Cependant, si votre fichier csv était corrompu, procédez comme suit:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01
Dennis, 40+, None-Ur-Bz

Ensuite, spécifier dtype={'age':int} Interrompt la commande .read_csv(), car elle ne peut pas convertir "40+" En int. Donc, désinfectez soigneusement vos données!

Ici vous pouvez voir comment l'utilisation de la mémoire d'un pandas dataframe est beaucoup plus élevée lorsque les flottants sont conservés sous forme de chaînes:

Essayez vous-même

df = pd.DataFrame(pd.np.random.choice(['1.0', '0.6666667', '150000.1'],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 224544 (~224 MB)

df = pd.DataFrame(pd.np.random.choice([1.0, 0.6666667, 150000.1],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 79560 (~79 MB)
30
firelynx

J'ai eu le même problème de mémoire avec la simple lecture d'un fichier texte délimité par des tabulations d'environ 1 Go (plus de 5,5 millions d'enregistrements), ce qui a résolu le problème de mémoire:

df = pd.read_csv(myfile,sep='\t') # didn't work, memory error
df = pd.read_csv(myfile,sep='\t',low_memory=False) # worked fine and in less than 30 seconds

Spyder 3.2.3 Python 2.7.13 64bits

4
mooseman

J'utilise Pandas sur ma machine Linux et j'ai fait face à de nombreuses fuites de mémoire qui n'ont été résolues qu'après la mise à niveau Pandas vers la dernière version après le clonage depuis github.

3
Tarik

Il n'y a pas d'erreur pour Pandas 0.12.0 et NumPy 1.8.0.

J'ai réussi à créer un gros DataFrame et à l'enregistrer dans un fichier csv, puis à le lire avec succès. S'il vous plaît voir l'exemple ici . La taille du fichier est de 554 Mo (Cela a même fonctionné pour un fichier de 1,1 Go, a pris plus de temps pour générer une fréquence d'utilisation de 30 Go du fichier de 30 secondes). Bien que j'ai 4Gb de RAM disponible.

Ma suggestion est d'essayer de mettre à jour les pandas. Une autre chose qui pourrait être utile est d’essayer d’exécuter votre script à partir de la ligne de commande, parce que pour R, vous n’utilisez pas Visual Studio (cela a déjà été suggéré dans les commentaires de votre question), il dispose donc de davantage de ressources.

2
Oleksandr

J'ai rencontré ce problème également lorsque j'exécutais une machine virtuelle, ou ailleurs, lorsque la mémoire est très limitée. Cela n'a rien à voir avec pandas ou numpy ou csv), mais cela se produira toujours si vous essayez d'utiliser plus de mémoire que vous êtes censé utiliser, pas même en python.

La seule chance que vous avez est ce que vous avez déjà essayé, essayez de décomposer le gros truc en morceaux plus petits qui tiennent dans la mémoire.

Si vous vous êtes déjà demandé ce qu'est vraiment MapReduce, vous l'avez découvert vous-même ... MapReduce essaierait de répartir les morceaux sur de nombreuses machines, vous essaieriez de traiter le morceau sur une machine après l'autre.

Ce que vous avez découvert avec la concaténation des fichiers de morceaux peut être un problème, peut-être qu'une copie est nécessaire pour cette opération ... mais au final, cela vous sauvera peut-être dans votre situation actuelle, mais si votre csv devient un peu plus grand vous pourriez encore vous heurter à ce mur ...

Il se pourrait également que pandas soit si intelligent qu’il ne charge en fait que les fragments de données individuels dans la mémoire si vous faites quelque chose avec cela, comme concaténer un gros fichier??

Plusieurs choses que vous pouvez essayer:

  • Ne chargez pas toutes les données à la fois, mais les divisez en plusieurs morceaux
  • Autant que je sache, hdf5 est capable de faire ces morceaux automatiquement et ne charge que la partie sur laquelle votre programme travaille actuellement
  • Regardez si les types sont ok, une chaîne '0.111111' a besoin de plus de mémoire qu'un float
  • De quoi avez-vous réellement besoin? Si l'adresse est une chaîne, vous n'en aurez peut-être pas besoin pour l'analyse numérique ...
  • Une base de données peut aider à accéder et à charger uniquement les pièces dont vous avez réellement besoin (par exemple, uniquement les 1% d'utilisateurs actifs)
1

Bien que ce soit une solution de contournement qui ne soit pas vraiment une solution, je voudrais essayer de convertir ce fichier CSV en fichier JSON (ce qui devrait être trivial) et d’utiliser read_json méthode à la place - j’ai écrit et lu des fichiers JSON/data considérables (en centaines de Mo) dans Pandas de cette façon, sans aucun problème.

0
LetMeSOThat4U

J'ai essayé chunksize en lisant un gros fichier CSV

reader = pd.read_csv(filePath,chunksize=1000000,low_memory=False,header=0)

La lecture est maintenant la liste. Nous pouvons itérer le reader et écrire/ajouter au nouveau csv ou effectuer n'importe quelle opération

for chunk in reader:
    print(newChunk.columns)
    print("Chunk -> File process")
    with open(destination, 'a') as f:
        newChunk.to_csv(f, header=False,sep='\t',index=False)
        print("Chunk appended to the file")
0
muTheTechie