การลดการใช้หน่วยความจำใน Python ทำได้ยากเนื่องจากPython ไม่ปล่อยหน่วยความจำกลับสู่ระบบปฏิบัติการจริงๆ หากคุณลบอ็อบเจ็กต์หน่วยความจำจะพร้อมใช้งานสำหรับออบเจ็กต์ Python ใหม่ แต่ไม่free()
กลับไปที่ระบบ ( ดูคำถามนี้ )
หากคุณยึดติดกับอาร์เรย์ตัวเลขเหล่านั้นจะเป็นอิสระ แต่วัตถุแบบบรรจุกล่องจะไม่
>>> 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
การลดจำนวน Dataframes
Python เก็บหน่วยความจำของเราไว้ที่ลายน้ำสูง แต่เราสามารถลดจำนวน dataframes ทั้งหมดที่เราสร้างได้ เมื่อต้องการแก้ไขดาต้าเฟรมของคุณคุณinplace=True
จึงไม่ต้องสร้างสำเนา
gotcha ทั่วไปอีกตัวหนึ่งถือครองสำเนาของดาต้าเฟรมที่สร้างไว้ก่อนหน้านี้ใน ipython:
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}
คุณสามารถแก้ไขได้โดยพิมพ์%reset Out
เพื่อล้างประวัติของคุณ หรือคุณสามารถปรับจำนวนประวัติที่ ipython เก็บไว้ได้ipython --cache-size=5
(ค่าเริ่มต้นคือ 1000)
การลดขนาด Dataframe
หากเป็นไปได้ให้หลีกเลี่ยงการใช้ประเภทวัตถุ
>>> df.dtypes
foo float64 # 8 bytes per value
bar int64 # 8 bytes per value
baz object # at least 48 bytes per value, often more
ค่าที่มีอ็อบเจ็กต์ dtype อยู่ในกล่องซึ่งหมายความว่าอาร์เรย์ numpy มีเพียงตัวชี้และคุณมีวัตถุ Python แบบเต็มในฮีปสำหรับทุกค่าในดาต้าเฟรมของคุณ ซึ่งรวมถึงสตริง
ในขณะที่ numpy รองรับสตริงขนาดคงที่ในอาร์เรย์ แต่แพนด้าก็ไม่ทำ ( ทำให้ผู้ใช้สับสน ) สิ่งนี้สามารถสร้างความแตกต่างอย่างมีนัยสำคัญ:
>>> 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
คุณอาจต้องการหลีกเลี่ยงการใช้คอลัมน์สตริงหรือหาวิธีแทนข้อมูลสตริงเป็นตัวเลข
หากคุณมีดาต้าเฟรมที่มีค่าซ้ำหลายค่า (NaN เป็นเรื่องปกติมาก) คุณสามารถใช้โครงสร้างข้อมูลแบบกระจัดกระจายเพื่อลดการใช้หน่วยความจำ:
>>> 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
การดูการใช้งานหน่วยความจำ
คุณสามารถดูการใช้งานหน่วยความจำ ( เอกสาร ):
>>> 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
สำหรับแพนด้า 0.17.1 คุณสามารถdf.info(memory_usage='deep')
ดูการใช้หน่วยความจำรวมถึงวัตถุ
gc
โมดูลและเรียกใช้gc.collect()
แต่อาจไม่สามารถกู้คืนหน่วยความจำได้