NumPy 字符串数组的内存使用量远远大于对象数组的内存占用量



我仍然是numpy的新手,并且在numpy的dtypes周围搞砸了,发现针对字符串(aka'U'(的dtype比对象类型所使用的存储空间更多。说明这一事实的代码下面是:

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)

结果是:

800000
2400000

我的问题如下:

1(为什么会发生这种情况?为什么dtype ='u6'占记忆的3倍,是dtype = object

2(是否有一种方法可以创建一个字符串numpy数组,该字符串占用的存储空间比dtype =对象少?

预先感谢您

编辑:我想解释说我的帖子不是另一帖的副本,因为我的帖子是关于内存使用的,而另一篇文章没有提及有关dtype ='u'vs dtype的内存使用情况的任何内容='对象'

edit2:尽管我已经从其他帖子中学到了一些新的东西,但不幸的是,另一个帖子没有回答我的问题,因为我的帖子是关于记忆使用的,而另一篇文章没有提及有关dtype ='u的内存使用情况的任何信息'vs 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

使用2'u6'字符串,大小跳动48、4个字节/char *2元素 *6个char

使用bytestring dtype(PY2的默认值(,跳跃为12,2*6。

bytestring更紧凑,但请注意显示:

In [31]: np.array(['smile','smile1'],'S6')                                                           
Out[31]: array([b'smile', b'smile1'], dtype='|S6')

对于对象dtype:

In [32]: sys.getsizeof(np.array(['smile','smile1'],object))                                          
Out[32]: 112

那是16个字节-2*8

,但加上python字符串的大小,一个额外的133字节

In [33]: sys.getsizeof('smile')                                                                      
Out[33]: 78
In [34]: sys.getsizeof('smile1')                                                                     
Out[34]: 55

和bytestsrings:

In [36]: sys.getsizeof(b'smile')                                                                     
Out[36]: 38
In [37]: sys.getsizeof(b'smile1')                                                                    
Out[37]: 39

请注意,当我添加字节字符时,大小会增加1。但是当我添加一个Unicode字符时,大小实际上会减小。Unicode字符串的大小更难预测。我认为它最多可以分配4个字节,但实际数字取决于字符和编码。通常,我们不会尝试微型Mange Python的字符串处理。(最重要的是,我相信Python有某种字符串缓存。(

但是当您分配

X[ind1] = 'smile'
X[ind2] = 'smile2'

在对象情况下,您可以制作两个python字符串,并将引用(指针(分配给数组。因此,内存使用量是数组(1000 ...*8字节(加上这两个字符串的133个字节。

在" u6"情况下,每个元素都占用4*6字节,无论是"微笑"还是" smile1"(或" s"(。数组的每个元素都使用相同的空间,而不管是否需要所有这些空间来表示字符串。

总体字符串不是numpy强度。当字符串的大小相似,如果字符串的长度变化,重复和/或是Unicode时," U"或" S" dtype的内存使用情况还可以。numpy不做自己的字符串处理太多。np.char功能只是Python String方法的薄包装器。

pandas选择使用object dtype而不是字符串dtypes。

如果您查看内存中的每种数据类型的大小:

import numpy as np
dt = np.dtype('object')
print('object = %i bytes' % dt.itemsize)
dt = np.dtype('U6')
print('U6 = %i bytes' % dt.itemsize)

输出:

object = 8 bytes
U6 = 24 bytes

最新更新