Erreur de mémoire avec de grands ensembles de données pour les pandas.concat et numpy.ajouter
Je suis confronté à un problème où je dois générer de grandes DataFrames dans une boucle (50 itérations de calcul à chaque fois deux 2000 x 800 pandas DataFrames). Je tiens à garder les résultats en mémoire dans un plus grand DataFrame, ou dans un dictionnaire de la forme de la structure.
Lors de l'utilisation de pandas.concat, j'obtiens une erreur de mémoire, à un certain point dans la boucle. Le même phénomène se produit lors de l'utilisation de numpy.ajouter à stocker les résultats dans un dictionnaire de numpy des tableaux plutôt que dans un DataFrame. Dans les deux cas, j'ai encore beaucoup de mémoire disponible (plusieurs GO). Est-ce trop de données pour des pandas ou des numpy? Sont-il plus efficace de la mémoire des moyens pour stocker mes données sans l'enregistrer sur le disque?
Comme un exemple, le script suivant échoue dès que nbIds
est supérieure à 376:
import pandas as pd
import numpy as np
nbIds = 376
dataids = range(nbIds)
dataCollection1 = []
dataCollection2 = []
for bs in range(50):
newData1 = pd.DataFrame( np.reshape(np.random.uniform(size =
2000 * len(dataids)),
(2000,len(dataids ))))
dataCollection1.append( newData1 )
newData2 = pd.DataFrame( np.reshape(np.random.uniform(size =
2000 * len(dataids)),
(2000,len(dataids ))))
dataCollection2.append( newData2 )
dataCollection1 = pd.concat(dataCollection1).reset_index(drop = True)
dataCollection2 = pd.concat(dataCollection2).reset_index(drop = True)
Le code ci-dessous échoue lorsque nbIds
est 665 ou plus
import pandas as pd
import numpy as np
nbIds = 665
dataids = range(nbIds)
dataCollection1 = dict( (i , np.array([])) for i in dataids )
dataCollection2 = dict( (i , np.array([])) for i in dataids )
for bs in range(50):
newData1 = np.reshape(np.random.uniform(size = 2000 * len(dataids)),
(2000,len(dataids )))
newData1 = pd.DataFrame(newData1)
newData2 = np.reshape(np.random.uniform(size = 2000 * len(dataids)),
(2000,len(dataids)))
newData2 = pd.DataFrame(newData2)
for i in dataids :
dataCollection1[i] = np.append(dataCollection1[i] ,
np.array(newData1[i]))
dataCollection2[i] = np.append(dataCollection2[i] ,
np.array(newData2[i]))
J'ai besoin de calculer les deux DataFrames à chaque fois, et pour chaque élément i
de dataids
j'ai besoin d'obtenir une pandas Série ou un tableau numpy contenant 50 * 2000 numéros générés pour i
. Idéalement, j'ai besoin d'être en mesure de l'exécuter avec nbIds
égale à 800 ou plus.
Est-il un moyen simple de faire cela?
Je suis en utilisant 32 bits Python Python 2.7.5, les pandas 0.12.0 et numpy 1.7.1.
Merci beaucoup pour votre aide!
Avec la première méthode (à l'aide de
pandas.concat
) le processus utilise 638 MO quand il échoue. Avec la seconde méthode (stocker les données dans un dictionnaire, des tableaux numpy) le processus atteint d'une utilisation de la mémoire de 1.113 GO avant d'échouer.Si votre environnement le permet, utilisez les pandas sur un 64 bits Python
Le code ci-dessus, en effet, semble fonctionner sur Python 64 bits. Cependant j'ai besoin pour le faire fonctionner pour Python 32 que j'en ai besoin pour être portable sur les systèmes 32 bit.
OriginalL'auteur Vidac | 2013-10-25
Vous devez vous connecter pour publier un commentaire.
C'est essentiellement ce que vous faites. Notez qu'il n'a pas beaucoup de différence à partir d'un point de vue de la mémoire si vous ne conversition à DataFrames avant ou après.
Mais vous pouvez spécifier dtype='float32' efficacement 1/2 de votre mémoire.
pd.DataFrame(np.concatenate([ np.random.uniform(size=2000 * 1000).reshape(2000,1000) for i in xrange(50) ]))
déclenche une erreur de mémoire sur mon système. La lignepd.DataFrame(np.concatenate([ np.random.uniform(size=2000 * 1000).astype('float32').reshape(2000,1000) for i in xrange(50) ]))
fonctionne mais déclenche une erreur de mémoire après le troisième appel, et avec la DataFrames dans mon code, à l'aide de float32 me permet de créer le premier mais pas le second DataFrame avant une erreur de mémoire se produit.comme un intervenant ci-dessus suggèrent, vous sont frapper un problème avec les versions 32 bits de répartition. il a besoin de trouver des blocs contigus afin de travailler. La façon dont vous créez des choses, par définition, seront fragment de la mémoire, de sorte qu'il peut ou peut ne pas fonctionner. le mieux est vraiment d'installer 64-bit python (addtl mémoire wont' aider avec 32-bit). L'ensemble de la concaténation des routines de copie. Vous pouvez également faire une petite taille.
OriginalL'auteur Jeff
Un simple (mais en utilisant le disque dur) serait d'utiliser simplement la mettre en veilleuse (un disque dur dict): http://docs.python.org/2/library/shelve.html
Pourquoi le downvote ? cette réponse est utile à l'une des questions.
Pourriez-vous commenter sur la façon dont exactement ce qui contribue à ce qui a été demandé? Parce que, selon leur propre description, Enterrent est juste le stockage persistant. Sens, vous devez tout d'abord charger le DataFrame de la mémoire, et ensuite utiliser Étagère de magasin, vous ne pouvez pas utiliser Étagère lieu de l'utilisation de mémoire de ce que je peux dire.
OriginalL'auteur tk.
Comme suggéré par usethedeathstar, Boud et Jeff dans les commentaires, le passage au 64 bits python fait le tour.
Si la perte de précision n'est pas un problème, l'utilisation d'float32 type de données comme suggéré par Jeff augmente également la quantité de données qui peuvent être traitées dans un environnement 32 bits.
OriginalL'auteur Vidac