Das Reduzieren der Speichernutzung in Python ist schwierig, da Python den Speicher nicht an das Betriebssystem zurückgibt . Wenn Sie Objekte löschen, steht der Speicher neuen Python-Objekten zur Verfügung, jedoch nicht free()
dem System ( siehe diese Frage) ).
Wenn Sie sich an numerische Numpy-Arrays halten, werden diese freigegeben, Box-Objekte jedoch nicht.
>>> import os, psutil, numpy as np
>>> def usage():
... process = psutil.Process(os.getpid())
... return process.get_memory_info()[0] / float(2 ** 20)
...
>>> usage() # initial memory usage
27.5
>>> arr = np.arange(10 ** 8) # create a large array without boxing
>>> usage()
790.46875
>>> del arr
>>> usage()
27.52734375 # numpy just free()'d the array
>>> arr = np.arange(10 ** 8, dtype='O') # create lots of objects
>>> usage()
3135.109375
>>> del arr
>>> usage()
2372.16796875 # numpy frees the array, but python keeps the heap big
Reduzieren der Anzahl der Datenrahmen
Python hält unseren Speicher auf einem hohen Wasserzeichen, aber wir können die Gesamtzahl der von uns erstellten Datenrahmen reduzieren. Bevorzugen inplace=True
Sie beim Ändern Ihres Datenrahmens, damit Sie keine Kopien erstellen.
Ein weiteres häufiges Problem ist das Festhalten an Kopien zuvor in ipython erstellter Datenrahmen:
In [1]: import pandas as pd
In [2]: df = pd.DataFrame({'foo': [1,2,3,4]})
In [3]: df + 1
Out[3]:
foo
0 2
1 3
2 4
3 5
In [4]: df + 2
Out[4]:
foo
0 3
1 4
2 5
3 6
In [5]: Out # Still has all our temporary DataFrame objects!
Out[5]:
{3: foo
0 2
1 3
2 4
3 5, 4: foo
0 3
1 4
2 5
3 6}
Sie können dies beheben, indem Sie eingeben %reset Out
, um Ihren Verlauf zu löschen. Alternativ können Sie anpassen, wie viel Verlauf ipython aufbewahrt ipython --cache-size=5
(Standard ist 1000).
Reduzieren der Datenrahmengröße
Vermeiden Sie nach Möglichkeit die Verwendung von Objekt-D-Typen.
>>> df.dtypes
foo float64 # 8 bytes per value
bar int64 # 8 bytes per value
baz object # at least 48 bytes per value, often more
Werte mit einem Objekttyp werden eingerahmt. Dies bedeutet, dass das numpy-Array nur einen Zeiger enthält und Sie für jeden Wert in Ihrem Datenrahmen ein vollständiges Python-Objekt auf dem Heap haben. Dies schließt Zeichenfolgen ein.
Während numpy Zeichenfolgen mit fester Größe in Arrays unterstützt, ist dies bei Pandas nicht der Fall ( dies führt zu Verwirrung bei den Benutzern ). Dies kann einen signifikanten Unterschied machen:
>>> import numpy as np
>>> arr = np.array(['foo', 'bar', 'baz'])
>>> arr.dtype
dtype('S3')
>>> arr.nbytes
9
>>> import sys; import pandas as pd
>>> s = pd.Series(['foo', 'bar', 'baz'])
dtype('O')
>>> sum(sys.getsizeof(x) for x in s)
120
Möglicherweise möchten Sie die Verwendung von Zeichenfolgenspalten vermeiden oder eine Möglichkeit finden, Zeichenfolgendaten als Zahlen darzustellen.
Wenn Sie einen Datenrahmen haben, der viele wiederholte Werte enthält (NaN ist sehr häufig), können Sie eine spärliche Datenstruktur verwenden , um die Speichernutzung zu reduzieren:
>>> df1.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 39681584 entries, 0 to 39681583
Data columns (total 1 columns):
foo float64
dtypes: float64(1)
memory usage: 605.5 MB
>>> df1.shape
(39681584, 1)
>>> df1.foo.isnull().sum() * 100. / len(df1)
20.628483479893344 # so 20% of values are NaN
>>> df1.to_sparse().info()
<class 'pandas.sparse.frame.SparseDataFrame'>
Int64Index: 39681584 entries, 0 to 39681583
Data columns (total 1 columns):
foo float64
dtypes: float64(1)
memory usage: 543.0 MB
Anzeigen der Speichernutzung
Sie können die Speichernutzung ( Dokumente ) anzeigen :
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 39681584 entries, 0 to 39681583
Data columns (total 14 columns):
...
dtypes: datetime64[ns](1), float64(8), int64(1), object(4)
memory usage: 4.4+ GB
Ab Pandas 0.17.1 können Sie auch die df.info(memory_usage='deep')
Speichernutzung einschließlich der Objekte anzeigen .
gc
Modul auch importieren und aufrufen,gc.collect()
aber er kann den Speicher möglicherweise nicht wiederherstellen