206 votes

Comment estimer la quantité de mémoire nécessaire à un DataFrame de Pandas ?

Je me suis demandé... Si je lis, disons, un fichier csv de 400 Mo dans un dataframe pandas (en utilisant read_csv ou read_table), y a-t-il un moyen d'estimer la quantité de mémoire nécessaire ? J'essaie juste d'avoir une meilleure idée des cadres de données et de la mémoire...

179voto

Aleksey Sivokon Points 1311

df.memory_usage() retournera le nombre d'octets qu'occupe chaque colonne :

>>> df.memory_usage()

Row_ID            20906600
Household_ID      20906600
Vehicle           20906600
Calendar_Year     20906600
Model_Year        20906600
...

Pour inclure les index, passez index=True .

Donc pour obtenir la consommation globale de mémoire :

>>> df.memory_usage(index=True).sum()
731731000

De plus, le fait de passer deep=True permet d'obtenir un rapport d'utilisation de la mémoire plus précis, qui tient compte de l'utilisation complète des objets contenus.

En effet, l'utilisation de la mémoire ne comprend pas la mémoire consommée par les éléments qui ne sont pas des composants du tableau si deep=False (cas par défaut).

145voto

Brian Burns Points 398

Voici une comparaison des différentes méthodes - sys.getsizeof(df) est le plus simple.

Pour cet exemple, df est un cadre de données avec 814 lignes, 11 colonnes (2 ints, 9 objets) - lu à partir d'un shapefile de 427kb

sys.getsizeof(df)

\>>> import sys
>>> sys.getsizeof(df)
(gives results in bytes)
462456

df.memory_usage()

\>>> df.memory\_usage()
...
(lists each column at 8 bytes/row)

>>> df.memory\_usage().sum()
71712
(roughly rows \* cols \* 8 bytes)

>>> df.memory\_usage(deep=True)
(lists each column's full memory usage)

>>> df.memory\_usage(deep=True).sum()
(gives results in bytes)
462432

df.info()

Imprime les informations du cadre de données sur la sortie standard. Techniquement, il s'agit de kibibytes (KiB), et non de kilobytes - comme le dit la docstring, "L'utilisation de la mémoire est indiquée en unités lisibles par l'homme (représentation en base 2)". Pour obtenir des octets, il faut donc multiplier par 1024, par exemple 451,6 KiB = 462 438 octets.

\>>> df.info()
...
memory usage: 70.0+ KB

>>> df.info(memory\_usage='deep')
...
memory usage: 451.6 KB

58voto

firelynx Points 56

J'ai pensé que je pourrais apporter quelques données supplémentaires à la discussion.

J'ai effectué une série de tests sur cette question.

En utilisant le programme python resource J'ai obtenu l'utilisation de la mémoire de mon processus.

Et en écrivant le csv dans un StringIO je pourrais facilement mesurer sa taille en octets.

J'ai réalisé deux expériences, chacune créant 20 cadres de données de tailles croissantes entre 10 000 lignes et 1 000 000 de lignes. Les deux ont 10 colonnes.

Dans la première expérience, je n'ai utilisé que des flottants dans mon jeu de données.

Voici comment la mémoire a augmenté par rapport au fichier csv en fonction du nombre de lignes. (Taille en mégaoctets)

Memory and CSV size in Megabytes as a function of the number of rows with float entries

Pour la deuxième expérience, j'ai utilisé la même approche, mais les données de l'ensemble de données ne comportaient que des chaînes courtes.

Memory and CSV size in Megabytes as a function of the number of rows with string entries

Il semble que la relation entre la taille du csv et la taille du dataframe peut varier considérablement, mais la taille en mémoire sera toujours supérieure d'un facteur 2-3 (pour les tailles de trame dans cette expérience).

J'adorerais compléter cette réponse avec d'autres expériences, veuillez commenter si vous voulez que j'essaie quelque chose de spécial.

32voto

Jeff Points 27612

Vous devez faire ça à l'envers.

In [4]: DataFrame(randn(1000000,20)).to_csv('test.csv')

In [5]: !ls -ltr test.csv
-rw-rw-r-- 1 users 399508276 Aug  6 16:55 test.csv

Techniquement, la mémoire c'est à peu près ceci (qui inclut les index)

In [16]: df.values.nbytes + df.index.nbytes + df.columns.nbytes
Out[16]: 168000160

Donc 168MB en mémoire avec un fichier de 400MB, 1M de lignes de 20 colonnes flottantes.

DataFrame(randn(1000000,20)).to_hdf('test.h5','df')

!ls -ltr test.h5
-rw-rw-r-- 1 users 168073944 Aug  6 16:57 test.h5

BEAUCOUP plus compact lorsqu'il est écrit comme un fichier HDF5 binaire.

In [12]: DataFrame(randn(1000000,20)).to_hdf('test.h5','df',complevel=9,complib='blosc')

In [13]: !ls -ltr test.h5
-rw-rw-r-- 1 users 154727012 Aug  6 16:58 test.h5

Les données étaient aléatoires, donc la compression ne sert pas à grand-chose.

13voto

Viktor Kerkez Points 11222

Oui, c'est possible. Pandas stockera vos données dans un fichier numpy à deux dimensions. ndarray en les regroupant par dtypes. ndarray est en fait un tableau de données C brut avec un petit en-tête. Vous pouvez donc estimer sa taille en multipliant simplement la taille de la variable dtype qu'il contient avec les dimensions du tableau.

Par exemple : si vous avez 1000 lignes avec 2 np.int32 et 5 np.float64 colonnes, votre DataFrame aura un 2x1000 np.int32 et un réseau 5x1000 np.float64 qui est :

4 octets*2*1000 + 8 octets*5*1000 = 48000 octets

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