我有一个内存映射,其中包含一个2D数组,我想从中创建一个numpy数组。理想情况下,我想避免复制,因为涉及的数组可能很大。
我的代码如下所示:
n_bytes = 10000
tagname = "Some Tag from external System"
map = mmap.mmap(-1, n_bytes, tagname)
offsets = [0, 5000]
columns = []
for offset in offsets:
#type and count vary in the real code, but for this dummy code I simply made them up. But I know the count and type for every column.
np_type = np.dtype('f4')
column_data = np.frombuffer(map, np_type, count=500, offset=offset)
columns.append(column_data)
# this line seems to copy the data, which I would like to avoid
data = np.array(columns).T
答案 0 :(得分:1)
我没有多少使用过frombuffer
,但我认为np.array
与那些数组一样,与传统构造的数组一样。
每个column_data
数组都有自己的数据缓冲区 - 您为其分配的mmap。但是np.array(columns)
从列表中的每个数组中读取值,并使用自己的数据缓冲区从它们构造一个新数组。
我喜欢使用x.__array_interface__
查看数据缓冲区位置(以及查看其他关键属性)。比较columns
和data
的每个元素的字典。
您可以使用连续的块从mmap构造一个二维数组。只需制作1d frombuffer
数组,然后reshape
数组。即使transpose
将继续使用该缓冲区(使用F
顺序)。切片和视图也使用它。
但除非你真的小心,否则你很快就会获得将数据放在别处的副本。只需data1 = data+1
创建一个新数组,或提前编制索引data[[1,3,5],:]
。任何concatenation
都相同。
来自bytestring buffers的2个数组:
In [534]: x=np.frombuffer(b'abcdef',np.uint8)
In [535]: y=np.frombuffer(b'ghijkl',np.uint8)
加入新数组
In [536]: z=np.array((x,y))
In [538]: x.__array_interface__
Out[538]:
{'data': (3013090040, True),
'descr': [('', '|u1')],
'shape': (6,),
'strides': None,
'typestr': '|u1',
'version': 3}
In [539]: y.__array_interface__['data']
Out[539]: (3013089608, True)
In [540]: z.__array_interface__['data']
Out[540]: (180817384, False)
x,y,z
的数据缓冲区位置完全不同
但重塑x
的数据不会改变
In [541]: x.reshape(2,3).__array_interface__['data']
Out[541]: (3013090040, True)
也不是2d转置
In [542]: x.reshape(2,3).T.__array_interface__
Out[542]:
{'data': (3013090040, True),
'descr': [('', '|u1')],
'shape': (3, 2),
'strides': (1, 3),
'typestr': '|u1',
'version': 3}
相同数据,不同观点
In [544]: x
Out[544]: array([ 97, 98, 99, 100, 101, 102], dtype=uint8)
In [545]: x.reshape(2,3).T
Out[545]:
array([[ 97, 100],
[ 98, 101],
[ 99, 102]], dtype=uint8)
In [546]: x.reshape(2,3).T.view('S1')
Out[546]:
array([[b'a', b'd'],
[b'b', b'e'],
[b'c', b'f']],
dtype='|S1')
答案 1 :(得分:0)
假设您有一个字节数组并且您知道它的维度,答案非常简单。 想象一下你在缓冲区中的原始RGB数据(每像素24位)(名为' buff') 尺寸为1024x768
#read the buffer into 1D byte array
arr = numpy.frombuffer(buff, dtype=numpy.uint8)
#now shape the array as you please
arr.shape = (768,1024,3)