mat*_*guy 2 python memory arrays string numpy
我对 Numpy 还很陌生,并且正在搞乱 Numpy 的dtypes,发现特定于字符串的 dtype(又名“U”)比对象类型占用更多的内存空间。说明这一事实的代码如下:
size= 100000
half_size = size//2
ind1 = np.arange(half_size)*2+1
ind2 = np.arange(half_size)*2
X = np.empty(size, dtype = 'object')
X[ind1] = 'smile'
X[ind2] = 'smile2'
W = np.empty(size, dtype = 'U6')
W[ind1] = 'smile'
W[ind2] = 'smile2'
print(X.nbytes)
print(W.nbytes)
Run Code Online (Sandbox Code Playgroud)
结果如下:
800000
2400000
Run Code Online (Sandbox Code Playgroud)
我的问题如下:
1)为什么会发生这种情况?为什么 dtype = 'U6' 占用的内存是 dtype = object 的 3 倍
2)有没有办法创建一个比 dtype = object 占用更少内存空间的字符串numpy数组?
先感谢您
编辑:我想解释一下,我的帖子不是另一篇帖子的重复,因为我的帖子是关于内存使用情况的,而另一篇文章没有提及有关 dtype = 'U' 与 dtype = 'object 的内存使用情况'
编辑2:虽然我已经从另一篇文章中学到了一些新东西,但不幸的是另一篇文章没有回答我的问题,因为我的文章是关于内存使用的,而另一篇文章没有提到有关 dtype = 'U' 与 dtype = 'U' 的内存使用情况dtype = '对象'
sys.getsizeof是检查内存使用情况的一种方法,尽管您必须明智地使用它,了解它到底测量的是什么。对于数组来说它工作得相当好。
没有任何元素的数组:
In [28]: sys.getsizeof(np.array([],'U6'))
Out[28]: 96
In [29]: sys.getsizeof(np.array(['smile','smile1'],'U6'))
Out[29]: 144
In [30]: sys.getsizeof(np.array(['smile','smile1'],'S6'))
Out[30]: 108
Run Code Online (Sandbox Code Playgroud)
使用2个'U6'字符串,大小跳变48,4字节/字符*2个元素*每个元素6个字符
对于字节串数据类型(Py2 的默认值),跳转为 12, 2*6。
bytestring 更紧凑,但请注意显示:
In [31]: np.array(['smile','smile1'],'S6')
Out[31]: array([b'smile', b'smile1'], dtype='|S6')
Run Code Online (Sandbox Code Playgroud)
对于对象数据类型:
In [32]: sys.getsizeof(np.array(['smile','smile1'],object))
Out[32]: 112
Run Code Online (Sandbox Code Playgroud)
那是 16 字节 - 2*8
但加上 Python 字符串的大小,额外的 133 个字节
In [33]: sys.getsizeof('smile')
Out[33]: 78
In [34]: sys.getsizeof('smile1')
Out[34]: 55
Run Code Online (Sandbox Code Playgroud)
对于字节串:
In [36]: sys.getsizeof(b'smile')
Out[36]: 38
In [37]: sys.getsizeof(b'smile1')
Out[37]: 39
Run Code Online (Sandbox Code Playgroud)
请注意,当我添加字节字符时,大小会增加 1。但是当我添加 unicode 字符时,大小实际上会减小。unicode 字符串的大小更难预测。我认为它可以为每个字符分配最多 4 个字节,但实际数量取决于字符和编码。通常我们不会尝试对 Python 的字符串处理进行微观管理。(最重要的是,我相信 Python 有某种字符串缓存。)
但是当你分配
X[ind1] = 'smile'
X[ind2] = 'smile2'
Run Code Online (Sandbox Code Playgroud)
在对象情况下,您创建两个 Python 字符串,并将引用(指针)分配给数组。因此,内存使用量是数组的内存使用量(1000...*8 字节)加上这 2 个字符串的 133 字节。
在“U6”情况下,每个元素占用 4*6 字节,无论它是“smile”还是“smile1”(或“s”)。数组的每个元素都使用相同的空间,无论是否需要全部元素来表示字符串。
一般来说,弦不是一个numpy强项。当字符串具有相似大小时,“U”或“S”数据类型的内存使用情况是可以的,但如果字符串长度不同、重复和/或是 unicode,则不太理想。 numpy它自己不做太多的字符串处理。这些np.char函数只是 Python 字符串方法的薄包装。
pandas选择使用object数据类型而不是字符串数据类型。